使用JQuery Validate Plugin验证具有相同名称的多个表单字段

时间:2009-05-31 09:03:32

标签: jquery validation jquery-validate

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

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

感谢您的关注。

12 个答案:

答案 0 :(得分:59)

由于我无法评论@scampbell的答案,我不知道如果它的声誉点或者线程刚刚结束,我对他的回答有所贡献,

您可以简单地覆盖只需要在需要它的页面中编辑的功能,而不是更改源文件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();
};

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

答案 1 :(得分:55)

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

这里发布了一个更优雅的解决方案: 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();
}

答案 2 :(得分:39)

我花了一些时间搜索并尝试不同的事情,最后我尝试了在多个字段上进行验证的最简单的方法。每个字段和它的克隆共享一组对每组唯一的类。我只是通过该类的输入循环并像往常一样添加了我的验证规则。我希望这可以帮助别人。

    $("#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





});

答案 3 :(得分:11)

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

答案 4 :(得分:4)

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);
};

答案 5 :(得分: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[]"]');

- 希望这有帮助!

答案 6 :(得分: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参数有实际的tab元素(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
        }
    }
});

答案 7 :(得分:2)

我正在使用“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 || .....

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

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

rulesCache中的

(this.id || this.name)

对不起,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;
        });
    };
}

});

答案 8 :(得分: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']);

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

答案 9 :(得分:0)

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

在您的情况下,不仅JQuery验证,而且服务器端表单验证器都会失败,因为它无法将输入分配给数据字段。假设您希望用户输入prename,lastname,e-mail-adress,fax(可选),并且所有输入字段都有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表单处理程序的文档,或者如果您自己编写它,请进行修改。

答案 10 :(得分:0)

对我来说,通过禁用调试

可以很容易地解决这个问题
 $("#_form").validate({
    debug:false,
    //debug: true,
    ...
    });

答案 11 :(得分:-1)

有一个简单的解决方案:

$(document).ready(function() {
   $(".form").each(function() {
      $(this).validate({
         ...
         ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form.
         ...
      });
   });
});