51

我有一个动态生成的表单,其中包含具有相同名称的输入字段(例如:“map”)。我没有更改字段名称或生成唯一字段名称的选项,因为表单处理程序代码 (Perl/CGI) 旨在处理输入值数组(在本例中@map)。

在这种情况下,如何使用 JQuery Validate Plugin来验证表单?具体来说,我希望提交数组的一个元素具有某个固定值。我目前正在使用一个自定义事件处理程序,它创建一个 JSON 对象,serializeArray()然后遍历它以确保满足条件。但是由于我在应用程序的其余部分中使用了验证插件,我想知道是否也可以在这里使用相同的插件来处理这种情况。

感谢您的关注。

4

12 回答 12

71

而不是更改源文件 jquery.validation 您可以简单地覆盖您需要仅在需要它的页面中编辑的功能。

一个例子是:

$.validator.prototype.checkForm = function() {
    //overriden in a specific page
    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) {
            for (var cnt = 0; cnt < this.findByName(elements[i].name).length; cnt++) {
                this.check(this.findByName(elements[i].name)[cnt]);
            }
        } else {
            this.check(elements[i]);
        }
    }
    return this.valid();
};

这可能不是最好的解决方案,但至少它避免了编辑源文件,这些文件可以在以后发布新版本时被替换。您覆盖的函数可能会或可能不会中断的地方。

于 2012-07-31T12:55:31.817 回答
58

我知道旧线程,但我在寻找解决同一问题的方法时遇到了它。

此处发布了一个更优雅的解决方案: http ://web-funda.blogspot.com/2009/05/jquery-validation-for-array-of-input.html

您只需编辑 jquery.validate.js 并将 checkForm 更改为

    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) {
            for (var cnt = 0; cnt < this.findByName( elements[i].name ).length; cnt++) {
                    this.check( this.findByName( elements[i].name )[cnt] );
            }
        } else {
            this.check( elements[i] );
        }
    }
    return this.valid();
}
于 2010-11-09T17:11:59.333 回答
43

当我最终尝试在多个字段上进行验证的最简单的方法时,我花了一些时间搜索和尝试不同的东西。每个字段及其克隆共享每个集合唯一的类。我只是用该类遍历输入并像往常一样添加我的验证规则。我希望这可能对其他人有所帮助。

    $("#submit").click(function(){
    $("input.years").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the years you worked"
            }
        } );            
    });

    $("input.employerName").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the employer name"
            }
        } );            
    }); 

    $("input.employerPhone").each(function(){
        $(this).rules("add", {
            required: true,
            minlength: 10,
            messages: {
                required: "Specify the employer phone number",
                minlength: "Not long enough"
            }
        } );            
    }); 

    $("input.position").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify your position"
            }
        } );            
    });             

    $("input.referenceName").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the reference name"
            }
        } );            
    });         

    $("input.referencePhone").each(function(){
        $(this).rules("add", {
            required: true,
            minlength: 10,
            messages: {
                required: "Specify your reference phone number",
                minlength: "Not long enough"
            }
        } );            
    });

// Now do your normal validation here, but don't assign rules/messages for the fields we just set them for





});
于 2009-08-06T02:12:48.863 回答
11

我刚刚从插件作者 Jörn Zaefferer 的一封邮件中了解到,除了单选按钮和复选框之外,验证要求字段名称是唯一的。

于 2009-06-01T04:47:03.283 回答
5

Jason 的回答可以解决问题,但我不想在我执行此操作的每个表单上添加额外的点击事件。

就我而言,我让验证插件认为以“[]”结尾的名称不同,即使它们可能具有相同的字段名。为此,我在 jquery.validate.js 加载后重写了这两个内部方法。

$.validator.prototype.elements= function() {
var validator = this,
    rulesCache = {};

// select all valid inputs inside the form (no submit or reset buttons)
// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
return $([]).add(this.currentForm.elements)
.filter(":input")
.not(":submit, :reset, :image, [disabled]")
.not( this.settings.ignore )
.filter(function() {
    !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

    // select only the first element for each name (EXCEPT elements that end in []), and only those with rules specified
    if ( (!this.name.match(/\[\]/gi) && this.name in rulesCache) || !validator.objectLength($(this).rules()) )
        return false;

    rulesCache[this.name] = true;
    return true;
});
};


$.validator.prototype.idOrName = function(element) {

// Special edit to get fields that end with [], since there are several [] we want to disambiguate them
// Make an id on the fly if the element doesnt have one
if(element.name.match(/\[\]/gi)) {
    if(element.id){
        return element.id;
    } else {
        var unique_id = new Date().getTime();

        element.id = new Date().getTime();

        return element.id;
    }
}

return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
};
于 2011-03-31T15:17:50.140 回答
3

只需使用输入的未使用属性来存储原始名称,然后只需重命名并附加索引即可:

function addMultiInputNamingRules(form, field, rules){    
    $(form).find(field).each(function(index){
    $(this).attr('alt', $(this).attr('name'));
    $(this).attr('name', $(this).attr('name')+'-'+index);
    $(this).rules('add', rules);
});

}

function removeMultiInputNamingRules(form, field){    
    $(form).find(field).each(function(index){
    $(this).attr('name', $(this).attr('alt'));
    $(this).removeAttr('alt');
});

}

然后在你设置你的验证器之后:

addMultiInputNamingRules('#form-id', 'input[name="multifield[]"]', { required:true });

当你完成验证后,像这样恢复:

removeMultiInputNamingRules('#form-id', 'input[alt="multifield[]"]');

- 希望这可以帮助!

于 2010-10-19T20:05:25.710 回答
3

我正在使用“jQuery 验证插件 1.7”。

为什么多个“$(:input)”共享同名元素没有被验证的问题

是 $.validator.element 方法:

elements: function() {
        var validator = this,
            rulesCache = {};

        // select all valid inputs inside the form (no submit or reset buttons)
        // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
        return $([]).add(this.currentForm.elements)
        .filter(":input")
        .not(":submit, :reset, :image, [disabled]")
        .not( this.settings.ignore )
        .filter(function() {
            !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

            // select only the first element for each name, and only those with rules specified
            if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
                return false;

            rulesCache[this.name] = true;
            return true;
        });
    },

条件

if ( this.name in rulesCache ||.....

评估共享相同名称的第二个和下一个元素 true....

解决方案将具有以下条件:

(this.id || this.name) 在 rulesCache

对不起,JS 清教徒,(this.id || this.name) 不是 100%...

当然,

rulesCache[this.name] = true;

行也必须适当更改。

所以 $.validator.prototype.elements 方法将是:

$(function () {
if ($.validator) {
    //fix: when several input elements shares the same name, but has different id-ies....
    $.validator.prototype.elements = function () {

        var validator = this,
            rulesCache = {};

        // select all valid inputs inside the form (no submit or reset buttons)
        // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
        return $([]).add(this.currentForm.elements)
        .filter(":input")
        .not(":submit, :reset, :image, [disabled]")
        .not(this.settings.ignore)
        .filter(function () {
            var elementIdentification = this.id || this.name;

            !elementIdentification && validator.settings.debug && window.console && console.error("%o has no id nor name assigned", this);

            // select only the first element for each name, and only those with rules specified
            if (elementIdentification in rulesCache || !validator.objectLength($(this).rules()))
                return false;

            rulesCache[elementIdentification] = true;
            return true;
        });
    };
}

});

于 2011-06-28T19:29:32.660 回答
3

这是我的做法。比以前提出的方法更容易一些:

function validateTab(tab) {
    var valid = true;
    $(tab).find('input').each(function (index, elem) {
        var isElemValid = $("#registrationForm").validate().element(elem);
        if (isElemValid != null) { //this covers elements that have no validation rule
            valid = valid & isElemValid;
        }
    });

    return valid;
}

就我而言,我有一个向导(有 3 个步骤),结果证明它更加复杂,因为我不想一次验证所有字段。我基本上将组件放在选项卡中,如果第一个选项卡有效,我会移至下一个选项卡,直到到达最后一个,然后提交所有数据。因此,tab那里的参数是实际的选项卡元素(即 a div)。然后,我将所有输入元素子元素循环到我的选项卡并检查它们的有效性。

其他都是标准的。


为了完整起见,这里是其余代码:表单提交的完成方式以及我的验证器的外观:

<a href="javascript:moveToNextTab(1)" class="button next">Submit</a>

这里的 js 函数调用:

function moveToNextTab(currentTab) {
    var tabs = document.getElementsByClassName("tab");
    //loop through tabs and validate the current one.
    //If valid, hide current tab and make next one visible.
}

我正在使用这些验证规则(我在 JQuery.ready 上创建):

$("#registrationForm").validate({
    rules: {
        birthdate: {
            required: true,
            date: true
        },
        name: "required",
        surname: "required",
        address: "required",
        postalCode: "required",
        city: "required",
        country: "required",
        email: {
            required: true,
            email: true
        }
    }
});
于 2012-01-17T16:12:26.337 回答
1

也许我错过了这一点,但由于验证器不适用于多个名称(尝试......失败!)我更改了我的表单以动态更改名称,设置规则,然后在提交时取消设置名称。

两种方法(忽略 wlog 的东西,它只是输出到控制台):

// convert the field names into generated ones to allow fields with the same names 
// to be validated individually. The original names are stored as data against the
// elements, ready to be replaced. The name is replaced with
// "multivalidate-<name>-<id>", e.g. original => 'multivalidate-original-1'

function setGeneratedNamesWithValidationRules(form, fields, rules) {

    var length = fields.length;

    for (var i=0; i < length; ++i ){
        var name = fields[i];

        var idCounter = 0;  
        // we match either the already converted generator names or the original
        $("form [name^='multivalidate-" + name + "'], form [name='" + name + "']").each(function() {
            // identify the real name, either from the stored value, or the actual name attribute
            var realName = $(this).data('realName');
            if (realName == undefined) {
                realName = $(this).attr("name");
                $(this).data('realName', realName);
            }

            wlog("Name: " + realName + " (actual: " + $(this).attr("name") + "), val: " + $(this).val() + ". Rules: " + rules[realName]);
            $(this).attr("name", "multivalidate-" + realName + "-" + idCounter);
            if (rules[realName]) {
                $(this).rules("add", rules[realName]);
            }
            idCounter++;
        });
    }
}

function revertGeneratedNames(form, fields) {

    var length = fields.length;

    for (var i=0; i < length; ++i ){
        var name = fields[i];
        wlog("look for fields names [" + name + "]");

        $("form [name^='multivalidate-" + name + "']").each(function() {
            var realName = $(this).data('realName');
            if (realName == undefined) {
                wlog("Error: field named [" + $(this).attr("name") + "] does not have a stored real name");
            } else {
                wlog("Convert [" + $(this).attr("name") + "] back to [" + realName + "]");
                $(this).attr("name", realName);
            }
        });
    }
}

在表单加载时,每当我动态添加另一行时,我都会调用 set 方法,例如

setGeneratedNamesWithValidationRules($("#my-dynamic-form"), ['amounts'], { 'amounts': 'required'} );

这会更改名称以允许单独验证。

在 submitHandler: thingumy 验证后我调用了revert,即

revertGeneratedNames(form, ['amounts']);

在发布数据之前将名称切换回原始名称。

于 2010-10-19T11:57:20.800 回答
1

对我来说,通过禁用调试很容易解决这个问题

 $("#_form").validate({
    debug:false,
    //debug: true,
    ...
    });
于 2015-04-05T10:00:05.657 回答
-1

有一个简单的解决方案:

$(document).ready(function() {
   $(".form").each(function() {
      $(this).validate({
         ...
         ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form.
         ...
      });
   });
});
于 2011-09-19T07:15:14.170 回答
-2

我认为您误解了 HTML 表单的工作原理。每个表单元素都需要有一个唯一的名称,除了允许您为一个数据字段选择一个/多个选项的多个复选框和按钮。

在您的情况下,不仅 JQuery 验证,而且服务器端表单验证器也会失败,因为它无法将输入分配给数据字段。假设,您希望用户输入姓名、姓氏、电子邮件地址、传真(可选)并且您的所有输入字段都有name="map"

然后您将在提交时收到这些列表:

map = ['Joe','Doe','joe.doeAThotmail.com','++22 20182238'] //All fields completed
map = ['Joe','Doe','joe.doeAThotmail.com'] //OK, all mandatory fields completed 
map = ['Doe', 'joe.doeAThotmail.com','++22 20182238']//user forgot prename, should yield error

您会发现无法可靠地验证此表单。

我建议重新访问您的 perl 表单处理程序的文档,或者如果您自己编写它,则对其进行调整。

于 2009-06-02T15:50:13.710 回答