使用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. ... }); }); });