Py学习  »  Jquery

jquery validate-要求在一个组中至少填写一个字段

Patrick McElhaney • 7 年前 • 2399 次点击  

我在使用优秀的jquery Validate Plugin 以验证某些表单。在一个表单上,我需要确保用户至少填写一组字段中的一个。我想我有一个很好的解决方案,想和大家分享。 请提出你能想到的改进建议。

我找不到做这件事的内置方法 Rebecca Murphey's custom validation method ,这很有帮助。

我从三个方面改进了这个:

  1. 让您传入字段组的选择器
  2. 指定要通过验证必须填充的组数
  3. 在组中的所有输入之一通过验证后立即将其显示为通过验证 验证。(见呼喊 Nick Craver 最后)

所以你可以说 “必须至少填充X个与选择器Y匹配的输入。”

最终结果是,标记如下:

<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图像作为背景,除非它有类 检查 ,在这种情况下,它会得到一个复选标记图像。

这是我目前的代码:

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."));

万岁!

大声叫喊

现在,我的代码只是盲目地将错误消息隐藏在其他匹配字段上,而不是重新验证它们,这意味着如果出现了另一个问题(例如“只允许数字,而您输入了字母”),它将被隐藏,直到用户尝试提交为止。这是因为我不知道如何避免上述评论中提到的反馈循环。我知道一定有办法,所以 I asked a question 尼克克拉弗 启发了我。谢谢,尼克!

问题已解决

这本来是一个“让我分享这个,看看是否有人可以建议改进”的问题。虽然我仍然欢迎反馈,但我认为在这一点上已经很完整了。(它可以短一些,但我希望它读起来容易,不一定简洁。)所以好好享受吧!

update-now是jquery验证的一部分

这是 officially added to jQuery Validation 4/3/2012。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40546
文章 [ 9 ]  |  最新文章 7 年前
Rinat
Reply   •   1 楼
Rinat    16 年前

谢谢,内森。你帮我省了很多时间。

但是,我必须注意到这个规则还没有jquery.noconflict()就绪。因此,必须用jquery替换所有的$ var $j = jQuery.noConflict()

我有一个问题:我如何让它表现得像内置规则?例如,如果我输入email,则消息“please enter valid email”将自动消失,但如果我填写组字段之一,则错误消息将保留。

Rocket Hazmat
Reply   •   2 楼
Rocket Hazmat    14 年前

我对其他没有与此相关联的规则有问题,因此我更改了:

fields.valid();

对此:

var validator = this;
fields.each(function(){
   validator.valid(this);
});

我还做了一些(个人)改进,这是我正在使用的版本:

jQuery.validator.addMethod("require_from_group", function(value, element, options){
    var numberRequired = options[0],
    selector = options[1],
    $fields = $(selector, element.form),
    validOrNot = $fields.filter(function() {
        return $(this).val();
    }).length >= numberRequired,
    validator = this;
    if(!$(element).data('being_validated')) {
        $fields.data('being_validated', true).each(function(){
            validator.valid(this);
        }).data('being_validated', false);
    }
    return validOrNot;
}, jQuery.format("Please fill out at least {0} of these fields."));
squarecandy
Reply   •   3 楼
squarecandy    13 年前

这是我对rocket hazmat答案的破解,试图解决其他定义字段也需要验证的问题,但在成功填充一个字段时将所有字段标记为有效。

jQuery.validator.addMethod("require_from_group", function(value, element, options){
    var numberRequired = options[0],
    selector = options[1],
    $fields = $(selector, element.form),
    validOrNot = $fields.filter(function() {
        return $(this).val();
    }).length >= numberRequired,
    validator = this;
    if(!$(element).data('being_validated')) {
        $fields.data('being_validated', true).each(function(){
            validator.valid(this);
        }).data('being_validated', false);
    }
    if (validOrNot) {
    $(selector).each(function() {
            $(this).removeClass('error');
            $('label.error[for='+$(this).attr('id')+']').remove();
        });
    }
    return validOrNot;
}, jQuery.format("Please fill out at least {0} of these fields."));

现在唯一剩下的问题是边的情况,字段是空的,然后填充,然后再次空…在这种情况下,错误将应用于单个字段而不是组。但这似乎不太可能以任何频率发生,在这种情况下,技术上仍然有效。

Andrew Roazen
Reply   •   4 楼
Andrew Roazen    16 年前

因为我正在处理的表单有几个克隆的区域,这些区域的输入是分组的,所以我向require_from_group构造函数传递了一个额外的参数,只更改了addMethod函数的一行:

var commonParent = $(element).parents(options[2]);

这样,选择器、id或元素名就可以传递一次:

jQuery.validator.addClassRules("reqgrp", {require_from_group: [1, ".reqgrp", 'fieldset']});

验证器会将验证限制为每个字段集中只有该类的元素,而不是尝试计算表单中所有.reqgrp类元素。

Michael Gundlach
Reply   •   5 楼
Michael Gundlach    17 年前

在php中,以$开头的变量名是必需的,但在javascript中却是非常奇怪的(imho)。另外,我相信你会把它称为“$module”两次和“module”一次,对吧?看来这段代码不应该起作用。

另外,我不确定这是否是正常的jquery插件语法,但我可能会在addmethod调用上方添加注释,解释您完成了什么。即使使用上面的文本描述,也很难遵循代码,因为我不熟悉fieldset、:filled、value、element或selector引用什么。对于熟悉validate插件的人来说,这可能是显而易见的,所以要判断什么是正确的解释。

也许你可以用一些变量来自我记录代码;比如,

var atLeastOneFilled = module.find(...).length > 0;
if (atLeastOneFilled) {
  var stillMarkedWithErrors = module.find(...).next(...).not(...);
  stillMarkedWithErrors.text("").addClass(...)

(假设我真的理解了这些代码块的含义!:)

我不太清楚“module”到底是什么意思——你能给这个变量起个更具体的名字吗?

总的来说,代码不错!

docflabby
Reply   •   6 楼
docflabby    13 年前

我已经提交了 patch 这不会受到当前版本所带来的问题的影响(即“Required”选项在其他字段上停止正常工作,关于当前版本的问题的讨论正在进行 github .

http://jsfiddle.net/f887W/10/

jQuery.validator.addMethod("require_from_group", function (value, element, options) {
var validator = this;
var minRequired = options[0];
var selector = options[1];
var validOrNot = jQuery(selector, element.form).filter(function () {
    return validator.elementValue(this);
}).length >= minRequired;

// remove all events in namespace require_from_group
jQuery(selector, element.form).off('.require_from_group');

//add the required events to trigger revalidation if setting is enabled in the validator
if (this.settings.onkeyup) {
    jQuery(selector, element.form).on({
        'keyup.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.onfocusin) {
    jQuery(selector, element.form).on({
        'focusin.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.click) {
    jQuery(selector, element.form).on({
        'click.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.onfocusout) {
    jQuery(selector, element.form).on({
        'focusout.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

return validOrNot;
}, jQuery.format("Please fill at least {0} of these fields."));
Walter Kelly
Reply   •   7 楼
Walter Kelly    15 年前

谢谢肖恩。这解决了代码忽略其他规则的问题。

我还做了一些更改,以便“请至少填写1个字段…”消息显示在单独的div中,而不是显示在所有字段之后。

输入表单验证脚本

showErrors: function(errorMap, errorList){
            $("#form_error").html("Please fill out at least 1 field before submitting.");
            this.defaultShowErrors();
        },

把这个加到页面的某个地方

<div class="error" id="form_error"></div>

添加到require_from_group method addmethod函数

 if(validOrNot){
    $("#form_error").hide();
}else{
    $("#form_error").show();
}
......
}, jQuery.format(" &nbsp;(!)"));
sean
Reply   •   8 楼
sean    15 年前

很好的解决方案。但是,我有一个问题,就是其他规定的规则不起作用。对表单执行.valid()为我修复了此问题。

if(!$(element).data('being_validated')) {
  var fields = $(selector, element.form);
  fields.data('being_validated', true); 
  $(element.form).valid();
  fields.data('being_validated', false);
}
Gerasimos
Reply   •   9 楼
Gerasimos    17 年前

那是个很好的解决办法内森。谢谢。

下面是一种使上述代码工作的方法,以防有人像我一样在集成时遇到问题:

内部代码 附加方法.js 文件:

jQuery.validator.addMethod("require_from_group", function(value, element, options) {
...// Nathan's code without any changes
}, jQuery.format("Please fill out at least {0} of these fields."));

// "filone" is the class we will use for the input elements at this example
jQuery.validator.addClassRules("fillone", {
    require_from_group: [1,".fillone"]
});

内部代码 HTML 文件:

<input id="field1" class="fillone" type="text" value="" name="field1" />
<input id="field2" class="fillone" type="text" value="" name="field2" />
<input id="field3" class="fillone" type="text" value="" name="field3" />
<input id="field4" class="fillone" type="text" value="" name="field4" />

别忘了包含额外的-methods.js文件!