Asp.net MVC源码分析--Model Validation(Client端)实现(2)
上一篇我们介绍了如果输出Client Validation 信息到浏览器,下面我们来分析一个MVC是如果实现JavaScript验证的。
一.TextFor 输出的Html文本
先来看一下标记了[Required] attribute的属性通过TextFor输出的Html代码:
<input data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" type="text" value="" class="valid">
-
data-val:是否需要客户端验证
-
data-val-required:验证类型和错误消息
二.jquery.validate.unobtrusive.js的实现
1.unobtrusive 自定义验证规则
1 var $jQval = $.validator,
2 adapters,
3 data_validation = "unobtrusiveValidation";
我们看到$jQval对象其实就是$.validator对象。
1 $jQval.unobtrusive = {
2 adapters: [],
3
4 adapters = $jQval.unobtrusive.adapters;
5 adapters.add = function (adapterName, params, fn) {
6 if (!fn) { // Called with no params, just a function
7 fn = params;
8 params = [];
9 }
10 this.push({ name: adapterName, params: params, adapt: fn });
11 return this;
12 };
13
14 adapters.add("required", function (options) {
15 if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
16 setValidationValues(options, "required", true);
17 }
18 });
19 }
上面代码第10行,我们看到unobtrusive把所有与MVC相关的验证规则都放到了$jQval.unobtrusive.adapters(Array)对象中. 那么这些验证规则如果被Jquery调用的呢?我们接着来看.
2.用Adapter模式与Jquery集成
下面我们看一下jquery.validate.unobtrusive.js的实现,当初始化时调用了$jQval.unobtrusive.parse方法请注意上面第42行,unobtrusive只对data-val设置为true的input控件进行验证 。
1 $(function () {
2 $jQval.unobtrusive.parse(document);
3 });
4
5 function validationInfo(form) {
6 var $form = $(form),
7 result = $form.data(data_validation);
8
9 if (!result) {
10 result = {
11 options: { // options structure passed to jQuery Validate's validate() method
12 errorClass: "input-validation-error",
13 errorElement: "span",
14 errorPlacement: $.proxy(onError, form),
15 invalidHandler: $.proxy(onErrors, form),
16 messages: {},
17 rules: {},
18 success: $.proxy(onSuccess, form)
19 },
20 attachValidation: function () {
21 $form.validate(this.options);
22 },
23 validate: function () { // a validation function that is called by unobtrusive Ajax
24 $form.validate();
25 return $form.valid();
26 }
27 };
28 $form.data(data_validation, result);
29 }
30
31 return result;
32 }
33
34 parse: function (selector) {
35 $(selector).find(":input[data-val=true]").each(function () {
36 $jQval.unobtrusive.parseElement(this, true);
37 });
38
39 $("form").each(function () {
40 var info = validationInfo(this);
41 if (info) {
42 info.attachValidation();
43 }
44 });
45 }
上面的代码第21行,就是调用了jQuery的valildate方法对form 表单进行验证,那么this.options 是怎么得到的呢?
是在$jQval.unobtrusive.parseElement方法里完成的。
1 parseElement: function (element, skipAttach) {
2
3 var $element = $(element),
4 form = $element.parents("form")[0],
5 valInfo, rules, messages;
6
7 if (!form) { // Cannot do client-side validation without a form
8 return;
9 }
10
11 valInfo = validationInfo(form);
12 valInfo.options.rules[element.name] = rules = {};
13 valInfo.options.messages[element.name] = messages = {};
14
15 $.each(this.adapters, function () {
16 var prefix = "data-val-" + this.name,
17 message = $element.attr(prefix),
18 paramValues = {};
19
20 if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
21 prefix += "-";
22
23 $.each(this.params, function () {
24 paramValues[this] = $element.attr(prefix + this);
25 });
26
27 this.adapt({
28 element: element,
29 form: form,
30 message: message,
31 params: paramValues,
32 rules: rules,
33 messages: messages
34 });
35 }
36 });
37
38 jQuery.extend(rules, { "__dummy__": true });
39
40 if (!skipAttach) {
41 valInfo.attachValidation();
42 }
43 },
小结:
- $jQval.unobtrusive 利用adapter模式,对jQuery的validate方法包装
- unobtrusive只对data-val设置为true的input控件进行验证 。