社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Jquery

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

Patrick McElhaney • 5 年前 • 1842 次点击  

我在使用优秀的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
 
1842 次点击  
文章 [ 9 ]  |  最新文章 5 年前
Rinat
Reply   •   1 楼
Rinat    15 年前

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

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

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

Rocket Hazmat
Reply   •   2 楼
Rocket Hazmat    13 年前

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

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    12 年前

这是我对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    15 年前

因为我正在处理的表单有几个克隆的区域,这些区域的输入是分组的,所以我向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    15 年前

在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    11 年前

我已经提交了 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    14 年前

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

我还做了一些更改,以便“请至少填写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    14 年前

很好的解决方案。但是,我有一个问题,就是其他规定的规则不起作用。对表单执行.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    15 年前

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

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

内部代码 附加方法.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文件!