使用JQueryvalidation插件validation具有相同名称的多个表单字段

我有一个dynamic生成的forms与input字段具有相同的名称(例如:“地图”)。 我没有select更改字段名称或生成唯一的字段名称,因为表单处理程序代码(Perl / CGI)被devise为处理input值数组(在本例中为@map )。

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

感谢您的关注。

我花了一些时间寻找和尝试不同的事情,最后我试图在多个领域进行validation的最微不足道的方式。 每个字段和它的克隆共享每个集合独有的类。 我只是通过该类的input,并像往常一样添加了我的validation规则。 我希望这可以帮助别人。

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

我知道的老线程,但我碰到它,寻找修复相同的问题。

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

由于我不能评论@scampbell的答案,我不知道如果它的声誉点或因为线程刚刚closures,我有他的答案贡献,

而不是更改源文件jquery.validation,你可以简单地覆盖只需要在需要它的页面编辑的function。

一个例子是:

 $.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(); }; 

这可能不是最好的解决scheme,但是至less它可以避免编辑稍后在新版本发布时可以replace的源文件。 您的覆盖function可能会或可能不会中断

我只是从插件作者JörnZaefferer的一封邮件中得知,除了单选button和checkbox外,validation要求字段名是唯一的。

杰森的答案将做的伎俩,但我不想在每一个表单上添加额外的点击事件。

在我的情况下,我有validation插件考虑以'[]'结尾不同的名称,即使它们可能具有相同的字段名称。 为此,我在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); }; 

只需使用input的未使用属性来存储原始名称,然后只需重新命名即可:

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

}

然后你设置你的validation器:

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

当你完成validation时,恢复如下所示:

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

– 希望这可以帮助!

这是我如何做到的。 比以前提出的方法容易一点:

 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步),事实certificate,这是更复杂的,因为我不想一次validation所有的领域。 我基本上把组件放在标签中,如果第一个标签是有效的,我将移动到下一个,直到我到达最后一个,然后提交所有数据。 因此, tab参数就是实际的tab元素(这是一个div )。 然后,我将所有input元素的子元素循环到我的选项卡,并检查它们的有效性。

其他一切都是标准的。


为了完整起见,这里是其余的代码:表单提交是如何完成的以及我的validation器的外观如何:

 <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. } 

我正在使用这些validation规则(我在JQuery.ready上创build的):

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

我正在使用“jQueryvalidation插件1.7”。

为什么多个“$(:input)”元素共享相同的名称不被validation

是$ .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; }); }, 

条件

如果(this.name在rulesCache || …..

评估第二个和下一个元素共享相同的名字真正….

解决办法是有条件:

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

});

也许我错过了这一点,但由于validation器不能与多个名称(尝试…失败!)我改变了我的表格dynamic更改名称,设置规则,然后取消设置提交的名称。

两种方法(忽略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>", eg 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); } }); } } 

在表单加载,并且每当我dynamic地添加另一行时,我调用set方法,例如

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

这改变了名字,以允许个人validation。

在submitHandler:thingumyvalidation后,我打电话回复,即

 revertGeneratedNames(form, ['amounts']); 

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

我想你误解了HTML表单的作用。 每个表单元素都需要有一个唯一的名称,除了多个checkbox和button,允许您为一个数据字段select一个/多个选项。

在你的情况下,不仅JQueryvalidation,而且服务器端的表单validation将失败,因为它不能分配input到数据字段。 假设你想让用户input姓名,姓氏,电子邮件地址,传真(可选),并且你所有的input字段都有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 

你会发现无法可靠地validation这个表单。

我build议重新访问你的perl表单处理程序的文档,或者如果你自己写的话,可以修改它。

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

  $("#_form").validate({ debug:false, //debug: true, ... }); 

有一个简单的解决scheme:

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