我正在创建一个需要填充至少一个字段的表单,并且所有输入必须是整数或小数。我正在使用jquery的验证插件进行验证。我已经重新设计了一些我发现here的东西,似乎可以部分地解决这个问题。现在我有:
<SCRIPT>
jQuery.validator.addMethod("require_from_group", function(value, element, options) {
var numberRequired = options[0];
var selector = options[1];
var validOrNot = $(selector, element.form).filter(function() {
// Each field is kept if it has a value
return $(this).val();
// Set to true if there are enough, else to false
}).length >= numberRequired;
if(!$(element).data('being_validated')) {
var fields = $(selector, element.form);
fields.data('being_validated', true);
fields.valid();
fields.data('being_validated', false);
}
return validOrNot;
// {0} below is the 0th item in the options field
}, jQuery.format("Please fill out at least {0} of these fields."));
$(document).ready(function(){
var container = $('#errorContainer');
$("#FORMMM").validate( {
rules: {
groceries: {digits: true,require_from_group: [1,".at_least_one"]},
gas: {digits: true,require_from_group: [1,".at_least_one"]},
hotels: {digits: true,require_from_group: [1,".at_least_one"]}
},
success: function(label) {
label.html(" ").addClass("checked");
},
errorContainer: container,
errorLabelContainer: $("ol", container),
wrapper: 'li',
meta: "validate"
});
});
</SCRIPT>
HTML在下面,在我的实际表单中有15个输入字段,我只是在这里凝结它:
<form action="results.php" target="_blank" id="FORMMM">
<div style="clear:both">
<label for="groceries">Groceries</label>
<div style="float:right">
$<input name="groceries" type="text" class="at_least_one idleField"></div>
</div>
<div style="clear:both">
<label for="gas">Gas</label>
<div style="float:right">
$<input name="gas" type="text" class="at_least_one idleField">
</div>
</div>
<div style="clear:both">
<label for="hotels">Hotels</label>
<div style="float:right">
$<input name="hotels" type="text" class="at_least_one idleField">
</div>
</div>
<div id="button">
<input name="" type="submit" value="Calculate" class="calc_button" style="cursor:hand">
</div>
</form>
<div id="errorContainer">
<h4>errors</h4>
<ol>
</ol>
</div>
目前验证存在两个问题。如果所有字段都留空,当我只需要一个字段时,我会收到3条错误消息!
另外,如果我在其中一个输入中输入一个字母,我会得到“仅数字”错误信息一秒钟,但表格仍然会提交,因为第二次测试至少填写一个字段组成因为没有数字。
我是以完全错误的方式做这件事的吗?我在这里或在jquery论坛上找到的所有例子似乎都不合适。我应该朝哪个方向解决这个问题?
答案 0 :(得分:4)
我似乎找到了解决方案。请参阅代码中的注释。 Live demo
jQuery.validator.addMethod(
"require_from_group", function(value, element, options) {
var numberRequired = options[0];
var selector = options[1];
var fields = $(selector, element.form);
var filled_fields = fields.filter(function() {
// it's more clear to compare with empty string
return $(this).val() != "";
});
var empty_fields = fields.not(filled_fields);
// we will mark only first empty field as invalid
if (filled_fields.length < numberRequired && empty_fields[0] == element) {
return false;
}
return true;
// {0} below is the 0th item in the options field
}, jQuery.format("Please fill out at least {0} of these fields."));
$(document).ready(function(){
var container = $('#errorContainer');
$("#FORMMM").validate( {
// We must to force validation of entire form because
// when we remove value from 2-nd field
// the 1-st field becomes invalid.
onfocusout: function() { $("#FORMMM").valid() },
onkeyup: function() { $("#FORMMM").valid() },
rules: {
// note: you can use variable to avoid repeating
// of the same code
groceries: {
number: true,
require_from_group: [1, ".at_least_one"]
},
gas: {
number: true,
require_from_group: [1,".at_least_one"]
},
hotels: {
number: true,
require_from_group: [1,".at_least_one"]
}
},
success: function(label) {
label.html(" ").addClass("checked");
},
errorContainer: container,
errorLabelContainer: $("ol", container),
wrapper: 'li',
meta: "validate"
});
});
答案 1 :(得分:1)
你有两个问题:
您可以在此处查看起始状态:http://jsfiddle.net/jclark/NR29t/1/;我唯一改变的是表单现在在提交时触发警报而不是提交表单。
一次服用这些,我将从#1开始。我注意到,如果非数字条目位于表单的最后一个字段,则数字检查将停止提交表单。否则,它将继续。事实证明问题出在您的require_from_group
方法中。在撰写时,重新验证整个表格:
if(!$(element).data('being_validated')) {
var fields = $(selector, element.form);
fields.data('being_validated', true);
fields.valid();
fields.data('being_validated', false);
}
阅读您关联的帖子以及在那里关联的帖子,这似乎存在,导致错误消息在第一个必需输入失去焦点时出现,而不是仅在提交时出现。这是您的使用要求吗?因为这似乎是第一个问题的原因。 “being_validated”逻辑阻止了一个无限链(其中元素一重新验证了元素二,它重新验证了元素一,无限制),但是,这仍然意味着在检查每个字段时,它将重新验证组表单中的所有字段。看起来这个重新验证导致了问题。我认为发生的事情是,如果第一个字段是非数字的,则记录该错误,但是当验证最后一个字段时,它会重新验证整个表单,但跳过 - 无效循环检查会导致跳过其他字段;由于最后一个字段有效,整个表单都会提交。
我大约98%肯定我有这个权利。但是,我知道删除该块可以消除这个问题。看到这个版本:
http://jsfiddle.net/jclark/NR29t/2/
现在是第二个问题。在场上显示所有错误的行为是设计的,通常是有意义的 - 只是不是一组字段是相互关联的。幸运的是,Validator提供了groups
选项,用于表示只应报告找到的第一个错误的一组字段。看到这个版本:
http://jsfiddle.net/jclark/NR29t/3/
提交时未填写任何字段,您只能看到一条消息。但是,存在一个新问题:“请仅输入数字”消息仅在您输入无效输入后立即显示,或者当该字段被聚焦时。我认为这是一个Validator错误;请参阅此Stack Overflow问题:jquery validate - groups and their labels。具体来说,如果输入3是填充但不是数字,则输入1和2有效(不包含非数字,并填充其他一些字段),所以我认为这是清除组的错误。
不幸的是,我目前还没有解决这个问题。上面链接的SO问题提出了一种有点脆弱的解决方法,即专门编写一个验证方法来立即检查所有字段,因此它们都会一起失败并且消息仍然存在。这是一个演示:
http://jsfiddle.net/jclark/NR29t/4/
这是自定义验证器:
jQuery.validator.addMethod("digits_for_group", function(value, element, selector) {
var validOrNot = $(selector, element.form).filter(function() {
// Each field is kept if it has a value
return $(this).val().search(/[^0-9]/) != -1;
// Set to true if there are enough, else to false
}).length == $(selector, element.form).length;
return validOrNot;
}, jQuery.format("Please enter only digits"));
它有效,但我不喜欢它;它需要重新执行数字检查;你还需要进行其他验证检查。
希望这有帮助。