• 用页面脚本扩展mvc自动添加的验证


    mvc中可以用DataAnnotations来对模型进行验证

    当在页面中引入

    jquery,jquery.validate,jquery.validate.unobtrusive这3个脚本的时候,会根据model上的设置自动生成验证

    [Required]
    public string Email { get; set; }
    比如我有这样的字段,他会在页面上生成必填的验证
    image
    默认错误信息是用span来呈现的
    image
    如果不希望使用默认设置,而希望在不同的页面,或在同一个页面的不同表单做不同的设置,用mvc自动生成的就很难实现了。
     
    其实validate本身是可以设置的
    $(function () {
        $("form").validate({
            errorElement: "div",
            rules: { Email: { email: true,required:true } }
        });
    });

    如类似上面的代码

    image

    image

    错误信息是用div来呈现的。

    如果,在一个引入了jquery.validate.unobtrusive的页面中,写入上面的语句,是没有用的

    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <script>
        $(function () {
            $("form").validate({
                errorElement: "div",
                rules: { Email: { email: true } }
            });
        });

    ……

    类似这样。因为unobtrusive先执行了,所以页面中用validate设置的无效

    让引入的js后执行

    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript" defer></script>

    在引用的时候加上defer,这样虽然引入的代码写在前面,但是执行是在后面

    imageimage

    加上以后,可以看到,页面中的代码起了作用。但是自动生成又失效了。必填验证没有了。

    查看unobtrusive的代码发现

    function validationInfo(form) {
        var $form = $(form),
            result = $form.data(data_validation);
        //如果直接在页面上用validate写了验证,就不做
            if (!result) {
               ……
           }
    
        return result;
    }

    他会先去看有没有验证信息,如果没有,才加,有就不加了。

    只好自己修改一下了。

    首先,仍然是通过对某一个表单进行设置,这样同一个页面上有多个表单的时候,可以其中一个变,而另一个不变

    image

    写一个扩展方法,传入设置,并记录在调用的对象上。其中,set_validation是自定义的一个字符串,相当于字典key

    $.extend($.fn, {
      
    setValidation:function(opt) {           
          
    $.data(this[0],set_validation,opt);
        }
    });

    修改validationInfo方法 if(!result)中的部分

    var defaults = {
        errorClass: "input-validation-error",
        errorElement: "span",
        errorPlacement: $.proxy(onError, form),
        invalidHandler: $.proxy(onErrors, form),
        messages: {},
        rules: {},
        success: $.proxy(onSuccess, form)
    };
    var opt = $form.data(set_validation);               
    var setting = $.extend(defaults, opt);
    result = {
        options: setting,

    ……

    把他直接写在options里的拿出来作为默认值

    读取通过setValidation方法加到表单上的设置

    把设置覆盖到默认值上作为最终的设置值。

    到目前为止,设置erroeElement等已经可以生效,但是rules和messages还是无效。

    原因在于

    parseElement: function (element, skipAttach) {

    方法中有这么两句

    valInfo.options.rules[element.name] = rules = {};
    valInfo.options.messages[element.name] = messages = {};

    他把rules和messages都清空了。我尝试不清空,但是发现有问题。我懒的研究他具体是怎么把那些规则加进去的了。好在在后面发现了一句

    jQuery.extend(rules, { "__dummy__": true });

    在方法基本已经结束的位置他还对rules做了操作

    于是在清空之前,记录下原始数据,在这里附加原始数据

    valInfo = validationInfo(form);
    //记录设置
    var settingRule = valInfo.options.rules[element.name];
    var settingMessage = valInfo.options.messages[element.name];
    valInfo.options.rules[element.name] = rules = {};
    valInfo.options.messages[element.name] = messages = {};

    最后

    //附加设置
    jQuery.extend(rules, { "__dummy__": true }, settingRule);
    jQuery.extend(messages, settingMessage);

    到此rules和messages也可以加进来了。

    页面调用

    $(function () {
        $("#form1").setValidation({
            errorElement:"div",
            rules: { Email: { email: true } }
        });
    });

    image

    上面的表单form1附加了用div显示,及email格式验证

    修改过的unobtrusive如下

       1: /// <reference path="jquery-1.5.1.js" />
       2: /// <reference path="jquery.validate.js" />
       3:  
       4: /*!
       5: ** Unobtrusive validation support library for jQuery and jQuery Validate
       6: ** Copyright (C) Microsoft Corporation. All rights reserved.
       7: */
       8:  
       9: /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
      10: /*global document: false, jQuery: false */
      11:  
      12: /*modify by czcz1024*/
      13: (function ($) {
      14:     var $jQval = $.validator,
      15:         adapters,
      16:         set_validation="unobtrusiveValidationSettings"
      17:         data_validation = "unobtrusiveValidation";
      18:  
      19:     function setValidationValues(options, ruleName, value) {
      20:         options.rules[ruleName] = value;
      21:         if (options.message) {
      22:             options.messages[ruleName] = options.message;
      23:         }
      24:     }
      25:  
      26:     function splitAndTrim(value) {
      27:         return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
      28:     }
      29:  
      30:     function escapeAttributeValue(value) {
      31:         // As mentioned on http://api.jquery.com/category/selectors/
      32:         return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
      33:     }
      34:  
      35:     function getModelPrefix(fieldName) {
      36:         return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
      37:     }
      38:  
      39:     function appendModelPrefix(value, prefix) {
      40:         if (value.indexOf("*.") === 0) {
      41:             value = value.replace("*.", prefix);
      42:         }
      43:         return value;
      44:     }
      45:  
      46:     function onError(error, inputElement) {  // 'this' is the form element
      47:         var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
      48:             replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;
      49:  
      50:         container.removeClass("field-validation-valid").addClass("field-validation-error");
      51:         error.data("unobtrusiveContainer", container);
      52:  
      53:         if (replace) {
      54:             container.empty();
      55:             error.removeClass("input-validation-error").appendTo(container);
      56:         }
      57:         else {
      58:             error.hide();
      59:         }
      60:     }
      61:  
      62:     function onErrors(form, validator) {  // 'this' is the form element
      63:         var container = $(this).find("[data-valmsg-summary=true]"),
      64:             list = container.find("ul");
      65:  
      66:         if (list && list.length && validator.errorList.length) {
      67:             list.empty();
      68:             container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
      69:  
      70:             $.each(validator.errorList, function () {
      71:                 $("<li />").html(this.message).appendTo(list);
      72:             });
      73:         }
      74:     }
      75:  
      76:     function onSuccess(error) {  // 'this' is the form element
      77:         var container = error.data("unobtrusiveContainer"),
      78:             replace = $.parseJSON(container.attr("data-valmsg-replace"));
      79:  
      80:         if (container) {
      81:             container.addClass("field-validation-valid").removeClass("field-validation-error");
      82:             error.removeData("unobtrusiveContainer");
      83:  
      84:             if (replace) {
      85:                 container.empty();
      86:             }
      87:         }
      88:     }
      89:  
      90:     function validationInfo(form) {
      91:         var $form = $(form),
      92:             result = $form.data(data_validation);
      93:         //如果直接在页面上用validate写了验证,就不做
      94:             if (!result) {
      95:                 //默认值
      96:                 var defaults = {
      97:                     errorClass: "input-validation-error",
      98:                     errorElement: "span",
      99:                     errorPlacement: $.proxy(onError, form),
     100:                     invalidHandler: $.proxy(onErrors, form),
     101:                     messages: {},
     102:                     rules: {},
     103:                     success: $.proxy(onSuccess, form)
     104:                 };
     105:                 var opt = $form.data(set_validation);               
     106:                 var setting = $.extend(defaults, opt);
     107:                 result = {
     108:                     options: setting,
     109:                     attachValidation: function () {
     110:                         $form.validate(this.options);
     111:                     },
     112:                     validate: function () {  // a validation function that is called by unobtrusive Ajax
     113:                         $form.validate();
     114:                         return $form.valid();
     115:                     }
     116:                 };
     117:             $form.data(data_validation, result);
     118:         }
     119:  
     120:         return result;
     121:     }
     122:  
     123:     $jQval.unobtrusive = {
     124:         adapters: [],
     125:  
     126:         parseElement: function (element, skipAttach) {
     127:             /// <summary>
     128:             /// Parses a single HTML element for unobtrusive validation attributes.
     129:             /// </summary>
     130:             /// <param name="element" domElement="true">The HTML element to be parsed.</param>
     131:             /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
     132:             /// validation to the form. If parsing just this single element, you should specify true.
     133:             /// If parsing several elements, you should specify false, and manually attach the validation
     134:             /// to the form when you are finished. The default is false.</param>
     135:             var $element = $(element),
     136:                 form = $element.parents("form")[0],
     137:                 valInfo, rules, messages;
     138:  
     139:             if (!form) {  // Cannot do client-side validation without a form
     140:                 return;
     141:             }
     142:  
     143:             valInfo = validationInfo(form);
     144:             //记录设置
     145:             var settingRule = valInfo.options.rules[element.name];
     146:             var settingMessage = valInfo.options.messages[element.name];
     147:             valInfo.options.rules[element.name] = rules = {};
     148:             valInfo.options.messages[element.name] = messages = {};
     149:  
     150:             $.each(this.adapters, function () {
     151:                 var prefix = "data-val-" + this.name,
     152:                     message = $element.attr(prefix),
     153:                     paramValues = {};
     154:  
     155:                 if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
     156:                     prefix += "-";
     157:  
     158:                     $.each(this.params, function () {
     159:                         paramValues[this] = $element.attr(prefix + this);
     160:                     });
     161:  
     162:                     this.adapt({
     163:                         element: element,
     164:                         form: form,
     165:                         message: message,
     166:                         params: paramValues,
     167:                         rules: rules,
     168:                         messages: messages
     169:                     });
     170:                 }
     171:             });
     172:  
     173:             //附加设置
     174:             jQuery.extend(rules, { "__dummy__": true }, settingRule);
     175:             jQuery.extend(messages, settingMessage);
     176:  
     177:             if (!skipAttach) {
     178:                 valInfo.attachValidation();
     179:             }
     180:         },
     181:  
     182:         parse: function (selector) {
     183:             /// <summary>
     184:             /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
     185:             /// with the [data-val=true] attribute value and enables validation according to the data-val-*
     186:             /// attribute values.
     187:             /// </summary>
     188:             /// <param name="selector" type="String">Any valid jQuery selector.</param>
     189:             $(selector).find(":input[data-val=true]").each(function () {
     190:                 $jQval.unobtrusive.parseElement(this, true);
     191:             });
     192:  
     193:             $("form").each(function () {
     194:                 var info = validationInfo(this);
     195:                 if (info) {
     196:                     info.attachValidation();
     197:                 }
     198:             });
     199:         }
     200:     };
     201:  
     202:     adapters = $jQval.unobtrusive.adapters;
     203:  
     204:     adapters.add = function (adapterName, params, fn) {
     205:         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
     206:         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
     207:         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
     208:         /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
     209:         /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
     210:         /// mmmm is the parameter name).</param>
     211:         /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
     212:         /// attributes into jQuery Validate rules and/or messages.</param>
     213:         /// <returns type="jQuery.validator.unobtrusive.adapters" />
     214:         if (!fn) {  // Called with no params, just a function
     215:             fn = params;
     216:             params = [];
     217:         }
     218:         this.push({ name: adapterName, params: params, adapt: fn });
     219:         return this;
     220:     };
     221:  
     222:     adapters.addBool = function (adapterName, ruleName) {
     223:         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
     224:         /// the jQuery Validate validation rule has no parameter values.</summary>
     225:         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
     226:         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
     227:         /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
     228:         /// of adapterName will be used instead.</param>
     229:     /// <returns type="jQuery.validator.unobtrusive.adapters" />
     230:  
     231:         if (adapterName == "dateiso") adapterName = "dateISO";
     232:         return this.add(adapterName, function (options) {
     233:             setValidationValues(options, ruleName || adapterName, true);
     234:         });
     235:     };
     236:  
     237:     adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
     238:         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
     239:         /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
     240:         /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
     241:         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
     242:         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
     243:         /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
     244:         /// have a minimum value.</param>
     245:         /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
     246:         /// have a maximum value.</param>
     247:         /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
     248:         /// have both a minimum and maximum value.</param>
     249:         /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
     250:         /// contains the minimum value. The default is "min".</param>
     251:         /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
     252:         /// contains the maximum value. The default is "max".</param>
     253:         /// <returns type="jQuery.validator.unobtrusive.adapters" />
     254:         return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
     255:             var min = options.params.min,
     256:                 max = options.params.max;
     257:  
     258:             if (min && max) {
     259:                 setValidationValues(options, minMaxRuleName, [min, max]);
     260:             }
     261:             else if (min) {
     262:                 setValidationValues(options, minRuleName, min);
     263:             }
     264:             else if (max) {
     265:                 setValidationValues(options, maxRuleName, max);
     266:             }
     267:         });
     268:     };
     269:  
     270:     adapters.addSingleVal = function (adapterName, attribute, ruleName) {
     271:         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
     272:         /// the jQuery Validate validation rule has a single value.</summary>
     273:         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
     274:         /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
     275:         /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
     276:         /// The default is "val".</param>
     277:         /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
     278:         /// of adapterName will be used instead.</param>
     279:         /// <returns type="jQuery.validator.unobtrusive.adapters" />
     280:         return this.add(adapterName, [attribute || "val"], function (options) {
     281:             setValidationValues(options, ruleName || adapterName, options.params[attribute]);
     282:         });
     283:     };
     284:  
     285:     $jQval.addMethod("__dummy__", function (value, element, params) {
     286:         return true;
     287:     });
     288:  
     289:     $jQval.addMethod("regex", function (value, element, params) {
     290:         var match;
     291:         if (this.optional(element)) {
     292:             return true;
     293:         }
     294:  
     295:         match = new RegExp(params).exec(value);
     296:         return (match && (match.index === 0) && (match[0].length === value.length));
     297:     });
     298:  
     299:     adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern");
     300:     adapters.addBool("creditcard").addBool("date").addBool("dateiso").addBool("digits").addBool("email").addBool("number").addBool("url");
     301:     adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
     302:     adapters.add("equalto", ["other"], function (options) {
     303:         var prefix = getModelPrefix(options.element.name),
     304:             other = options.params.other,
     305:             fullOtherName = appendModelPrefix(other, prefix),
     306:             element = $(options.form).find(":input[name=" + escapeAttributeValue(fullOtherName) + "]")[0];
     307:  
     308:         setValidationValues(options, "equalTo", element);
     309:     });
     310:     adapters.add("required", function (options) {
     311:         // jQuery Validate equates "required" with "mandatory" for checkbox elements
     312:         if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
     313:             setValidationValues(options, "required", true);
     314:         }
     315:     });
     316:     adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
     317:         var value = {
     318:             url: options.params.url,
     319:             type: options.params.type || "GET",
     320:             data: {}
     321:         },
     322:             prefix = getModelPrefix(options.element.name);
     323:  
     324:         $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
     325:             var paramName = appendModelPrefix(fieldName, prefix);
     326:             value.data[paramName] = function () {
     327:                 return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val();
     328:             };
     329:         });
     330:  
     331:         setValidationValues(options, "remote", value);
     332:     });
     333:     //扩展方法,记录设置的参数
     334:     $.extend($.fn, {
     335:         setValidation: function (opt) {            
     336:             $.data(this[0],set_validation,opt);
     337:         }
     338:     });
     339:  
     340:     $(function () {
     341:         $jQval.unobtrusive.parse(document);
     342:     });
     343: } (jQuery));

    另外,之前的文章中,介绍过如何通过设置DataType(DataType.Date)就自动生成日期类型的验证

    如果使用validation提供的date,只能验证2011/1/1 这样斜杠形式的,而不能验证2011-1-1横杠形式。要验证横杠需要用到的是dateISO,注意是区分大小写的,ISO必须是大写。但是改c#中date为dateISO就悲剧了。

    Validation type names in unobtrusive client validation rules must consist of only lowercase letters. Invalid name: "dateISO", client rule type: mvc4.Models.ModelClientValidationDateRule

    只能有小写字母,不知道为什么只能是小写。

    那这就小写吧。还是得改unobtrusive

    adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");

    首先找到这句,发现他只添加date验证,不添加dateiso验证,加上

    adapters.addBool("creditcard").addBool("date").

    addBool("dateiso"

    ).addBool("digits").addBool("email").addBool("number").addBool("url");

    然后找到addBool方法在return之前加上

    if (adapterName == "dateiso") adapterName = "dateISO";

    最终调用validate的时候,validate中的方法名是dateISO。

    下载

  • 相关阅读:
    macbook 无声音解决方案
    webapck dev server代理请求 json截断问题
    百度卫星地图开启
    服务器 nginx配置 防止其他域名绑定自己的服务器
    记一次nginx php配置的心路历程
    遇到npm报错read ECONNRESET怎么办
    运行svn tortoiseSvn cleanup 命令失败的解决办法
    svn add 命令 递归目录下所有文件
    m4出现Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
    Ubuntu下安装GCC,mpc、mpfr、gmp
  • 原文地址:https://www.cnblogs.com/czcz1024/p/2212708.html
Copyright © 2020-2023  润新知