我有一个动态生成的表单,其输入字段具有相同的名称(例如:“map”)。我没有更改字段名称或生成唯一字段名称的选项,因为表单处理程序代码(Perl / CGI)旨在处理输入值数组(在本例中为@map
)。
如何在这种情况下使用JQuery Validate Plugin来验证表单?具体来说,我希望提交的数组中只有一个元素具有一定的固定值。我目前正在使用一个自定义事件处理程序,它使用serializeArray()
创建一个JSON对象,然后遍历它以确保满足条件。但是因为我在应用程序的其余部分使用了Validate Plugin,所以我想知道是否也可以使用相同的插件来处理这样的情况。
感谢您的关注。
答案 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.
...
});
});
});