【发布时间】:2010-11-21 00:31:17
【问题描述】:
我正在使用出色的 jQuery Validate Plugin 来验证某些表单。在一个表单上,我需要确保用户至少填写一组字段中的一个。我想我有一个很好的解决方案,并想分享它。 请提出您能想到的任何改进建议。
找不到内置的方法,我搜索并找到了Rebecca Murphey's custom validation method,这非常有帮助。
我从三个方面改进了这一点:
- 让您为字段组传入一个选择器
- 让您指定必须填充该组的多少才能通过验证
- 只要其中一个通过验证,就将组中的所有输入显示为通过验证 验证。 (见最后对Nick Craver 的喊话。)
所以你可以说“必须填充匹配选择器 Y 的至少 X 个输入。”
最终结果,标记如下:
<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">
...是一组这样的规则:
// Both these inputs input will validate if
// at least 1 input with class 'productinfo' is filled
partnumber: {
require_from_group: [1,".productinfo"]
}
description: {
require_from_group: [1,".productinfo"]
}
第 3 项假设您在成功验证后将.checked 类添加到错误消息中。您可以按如下方式执行此操作,as demonstrated here。
success: function(label) {
label.html(" ").addClass("checked");
}
在上面链接的演示中,我使用 CSS 为每个 span.error 提供一个 X 图像作为其背景,除非它具有 .checked 类,在这种情况下它会获得一个复选标记图像。
到目前为止,这是我的代码:
jQuery.validator.addMethod("require_from_group", function(value, element, options) {
var numberRequired = options[0];
var selector = options[1];
//Look for our selector within the parent form
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;
// The elegent part - this element needs to check the others that match the
// selector, but we don't want to set off a feedback loop where each element
// has to check each other element. It would be like:
// Element 1: "I might be valid if you're valid. Are you?"
// Element 2: "Let's see. I might be valid if YOU'RE valid. Are you?"
// Element 1: "Let's see. I might be valid if YOU'RE valid. Are you?"
// ...etc, until we get a "too much recursion" error.
//
// So instead we
// 1) Flag all matching elements as 'currently being validated'
// using jQuery's .data()
// 2) Re-run validation on each of them. Since the others are now
// flagged as being in the process, they will skip this section,
// and therefore won't turn around and validate everything else
// 3) Once that's done, we remove the 'currently being validated' flag
// from all the elements
if(!$(element).data('being_validated')) {
var fields = $(selector, element.form);
fields.data('being_validated', true);
// .valid() means "validate using all applicable rules" (which
// includes this one)
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."));
万岁!
大喊
现在要大声疾呼 - 最初,我的代码只是盲目地将错误消息隐藏在其他匹配字段上,而不是重新验证它们,这意味着如果还有其他问题(比如“只允许数字并且您输入字母'),在用户尝试提交之前它一直被隐藏起来。这是因为我不知道如何避免上面 cmets 中提到的反馈循环。我知道一定有办法,所以I asked a question 和Nick Craver 启发了我。谢谢,尼克!
问题已解决
这最初是一个“让我分享一下,看看是否有人可以提出改进建议”之类的问题。虽然我仍然欢迎反馈,但我认为它在这一点上已经很完整了。 (它可以更短,但我希望它易于阅读,不一定要简洁。)所以尽情享受吧!
更新 - 现在是 jQuery 验证的一部分
这是 2012 年 4 月 3 日的officially added to jQuery Validation。
【问题讨论】:
-
另外,请参阅密切相关的规则 - “要么跳过这些字段,要么填写至少 X 个字段” - stackoverflow.com/questions/1888976/…
-
为什么一个任意输入要负责检查其他输入是否被填充?这没有意义。也许您可以在所涉及的元素中加入一些标记?
-
@dalbaeb - 我稍微澄清了这个例子。不是一个任意输入负责检查其他输入;这是一个组中的每个输入负责检查所有其他输入。
-
我就是这么想的,非常感谢!
-
谢谢,这对我有用,但是表单中的其他必填字段现在不再响应,除非它们在检查后获得和失去焦点。 (有人将此添加为您其他问题的答案,但必须标记它,因为它不是答案)。
标签: jquery validation jquery-plugins jquery-validate