当前位置 博文首页 > 程序员石磊:改造jquery validator ,支持多个name相同的验证

    程序员石磊:改造jquery validator ,支持多个name相同的验证

    作者:[db:作者] 时间:2021-08-08 19:25

    在项目中经常遇到,表单可以动态追加多行。但是追加的行中,input 文本框的name会重复。如果用jquery validator ,它只支持验证第一个input,后面的name相同的input不会被验证,怎么办呐?经过研究源码,提出了解决办法。
    基于jQuery Validation Plugin - v1.14.0 - 6/30/2015改造
    完整版下载
    在defaults默认配置中增加 duplicateValid,用户可自己配置是否开启重复name验证

     $.extend($.validator, {
            defaults: {
                duplicateValid: false,
                messages: {},
                groups: {},
                rules: {},
    
    

    改造checkForm函数,核心思想:根据name找到多个元素,for循环一一验证

    checkForm: function () {
                    this.prepareForm();
                    for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) {
                        if (this.findByName(elements[i].name).length != undefined && this.findByName(elements[i].name).length > 1 && this.settings.duplicateValid) {
                            for (var cnt = 0; cnt < this.findByName(elements[i].name).length; cnt++) {
                                try {
                                    this.check(this.findByName(elements[i].name)[cnt])
                                } catch (e) {
                                    window.console && console.log(e)
                                }
                            }
                        } else {
                            this.check(elements[i])
                        }
                    }
                    return this.valid()
                }
    

    改造showLabel函数

    showLabel: function (element, message) {
                    var place, group, errorID, error = this.errorsFor(element), elementID = this.idOrName(element),
                        describedBy = $(element).attr("aria-describedby");
                    var index = this.duplicateElementsIndex(element);
                    if (error.length) {
                        error.removeClass(this.settings.validClass).addClass(this.settings.errorClass);
                        error.html(message)
                    } else {
                        error = $("<" + this.settings.errorElement + ">").attr("id", elementID + "-error").addClass(this.settings.errorClass).html(message || "");
                        place = error;
                        if (this.settings.wrapper) {
                            place = error.hide().show().wrap("<" + this.settings.wrapper + "/>").parent()
                        }
                        if (this.labelContainer.length) {
                            this.labelContainer.append(place)
                        } else if (this.settings.errorPlacement) {
                            this.settings.errorPlacement(place, $(element))
                        } else {
                            place.insertAfter(element)
                        }
                        if (error.is("label")) {
                            var elementIDTemp = this.settings.duplicateValid ? elementID + "-" + index : elementID;
                            error.attr("for", elementIDTemp)
                        } else if (error.parents("label[for='" + elementID + "']").length === 0) {
                            errorID = error.attr("id").replace(/(:|\.|\[|\]|\$)/g, "\\$1");
                            if (!describedBy) {
                                describedBy = errorID
                            } else if (!describedBy.match(new RegExp("\\b" + errorID + "\\b"))) {
                                describedBy += " " + errorID
                            }
                            var describedByTemp = this.settings.duplicateValid ? describedBy + "-" + index : describedBy;
                            $(element).attr("aria-describedby", describedByTemp);
                            group = this.groups[element.name];
                            if (group) {
                                $.each(this.groups, function (name, testgroup) {
                                    if (testgroup === group) {
                                        $("[name='" + name + "']", this.currentForm).attr("aria-describedby", error.attr("id"))
                                    }
                                })
                            }
                        }
                    }
                    if (!message && this.settings.success) {
                        error.text("");
                        if (typeof this.settings.success === "string") {
                            error.addClass(this.settings.success)
                        } else {
                            this.settings.success(error, element)
                        }
                    }
                    this.toShow = this.toShow.add(error)
                }
    

    改造errorsFor函数

    errorsFor: function (element) {
                    var index = this.duplicateElementsIndex(element);
                    var name = this.idOrName(element), describer = $(element).attr("aria-describedby");
                    var nameTemp = this.settings.duplicateValid ? name + "-" + index : name;
                    var selector = "label[for='" + nameTemp + "'], label[for='" + nameTemp + "'] *";
                    if (describer) {
                        selector = selector + ", #" + describer.replace(/\s+/g, ", #")
                    }
                    return this.errors().filter(selector)
                }
    

    大功告成。
    调用实例

       formValidation = $("#esfyw").validate({
            duplicateValid:true,//验证重复元素
            errorPlacement:function(error,element) {
                if(element.is("input")){
                    error.appendTo(element.parent().parent().parent().prev());
                }else if(element.is("select")){
                    error.appendTo(element.parent().parent().prev());
                }
    
            } ,
            submitHandler:function(form){
               
                 ajaxPost(callbackfunction , callbackFailFunction);
            },
            rules: {
                districtCode:{
                    required:true
    
                }
                }
                 });
    
    cs