【问题标题】:jQuery Validate - "Either skip these fields, or fill at least X of them"jQuery Validate - “要么跳过这些字段,要么填写至少 X 个”
【发布时间】:2010-12-25 17:29:45
【问题描述】:

我在表单上使用jQuery Validation plugin。我有一些字段组是可选的,但需要是“全部或全部” - 如果您在组中填写一个输入,则必须填写所有字段。

例如,假设用户可以输入一个位置(街道、城市、州和邮政编码)或多个位置。你不必输入第二个位置,但如果你这样做了,只给出城市是不行的;我也需要那个状态和 zip。

为了解决这个问题,我编写了一个自定义规则——实际上只是对my previous rulerequire_from_group 的微小调整。这个叫skip_or_fill_minimum。以下是您的使用方法:

var validationrules = {
  rules: {
    location2address: {
    skip_or_fill_minimum: [4,'.location2']
  }
  //This input will validate if all 4 `.location2` inputs are filled,
  //or if all of them are left blank
}

var validator = $("#formtovalidate").validate(validationrules);  

这是自定义规则的代码:

jQuery.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
    var numberRequired = options[0];
    var selector = options[1];
    //Look for our selector within the parent form
    var numberFilled = $(selector, element.form).filter(function() {
         // Each field is kept if it has a value
         return $(this).val();
      }).length;
      var valid = numberFilled >= numberRequired || numberFilled === 0;

    //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 all the
    //elements check all the others which check all the others which
    //check all the others...
    //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);
      //.valid() means "validate using all applicable rules" (which includes this one)
      fields.data('being_validated', true);
      fields.validate(); //Changed from fields.valid();
      fields.data('being_validated', false);
    }
    return valid;
    // {0} below is the 0th item in the options field
    }, jQuery.format("Please either skip these fields or fill at least {0} of them."));

我主要发布此内容,以便其他在网上搜索解决方案的人可以找到它。仍然 - 有没有人看到改进的方法?

更新 - 现在是 jQuery 验证的一部分

这是 2012 年 4 月 3 日的officially added to jQuery Validation

【问题讨论】:

  • 2010 年 4 月 9 日更新了优雅的部分,重新​​检查其他组成员而不会导致无限循环。该逻辑由 Nick Craver 提供 - 请参阅有关我的相关规则的问题:stackoverflow.com/questions/1378472/…
  • 2010 年 8 月 22 日更新 - 在 fields.data 上将 .valid() 更改为 .validate();当只有这些字段返回 true 时,valid() 导致整个表单通过验证。

标签: jquery validation


【解决方案1】:

我的缩短和“优化”版本(更多链接 + 使用验证器自定义提供的选择器)。并希望减少选择操作。

仍然遭受与您的规则相同的错误——我的意思是删除error 类以及与我们的选择器匹配的所有元素上的错误标签并不是真正正确的。想象一下,您需要设置 4 个字段,但有 5 个。用户填写 4 个字段。他留下的第五个未填写,但在该字段上您还设置了requiredemail。这样即使他还没有解决,电子邮件的错误消息也会被删除。

jQuery.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
    var elems = $(element).parents('form').find(options[1]);
    var numberFilled = elems.filter(':filled').size();
    if (numberFilled >= options[0] || numberFilled == 0) {
        elems.removeClass('error');
        elems.next('label.error').not('.checked').text('').addClass('checked');
        return true;
    } else {
        elems.addClass('error');
    }
}, jQuery.format("Please either skip these fields or fill at least {0} of them."));

【讨论】:

  • 好建议。在某种程度上,为了成为一个清晰的例子,我的代码故意冗长,但我可以从你的代码中学到一些东西。谢谢!另外-您对删除错误的不正确行为是正确的。任何解决方法的想法?
【解决方案2】:

我花了很长时间才找到上述解决方案,解决组上方的字段无法验证的问题。

如果将 .valid() 更改为 .validate() 可以添加到密切相关的问题中 - herehere 为很多人都在问。

虽然此修复会阻止所有组标签在关键或模糊事件上显示或删除。我发现jitter's if else statement above 对解决这个问题很有帮助。

注意: stackoverflow 过去曾帮助我找到很多答案,但这是我的第一个实际贡献。感谢大家汇集这个解决方案。

【讨论】:

    【解决方案3】:

    这是我在 SO 上的第一篇文章,所以我希望我这样做是正确的,但在接受的解决方案中似乎存在错误。我已经为location2address 块(或rules 块,取决于你如何看待它)添加了右括号。

    var validationrules = {
      rules: {
        location2address: {
          skip_or_fill_minimum: [4,'.location2']
        }
      }
      //This input will validate if all 4 `.location2` inputs are filled,
      //or if all of them are left blank
    }
    var validator = $("#groovetime_entry").validate(validationrules); 
    

    【讨论】:

      【解决方案4】:

      我需要一些稍微不同的东西。它是一个搜索表单,包含 4 个其他搜索条件中的一个或两个名字或姓氏 AND/OR 1。

      我希望他们跳过或只输入一个(或 x)。我修改了上面的代码:

          jQuery.validator.addMethod("skip_or_fill_only_x", function (value, element, options) {
          var numberRequired = options[0];
          var selector = options[1];
          var numberFilled = $(selector, element.form).filter(function () {
              return $(this).val();
          }).length;
          //Changed this line from "numberFilled >=" to "numberFilled ==="
          var valid = numberFilled === numberRequired || numberFilled === 0;
          if (!$(element).data('being_validated')) {
              var fields = $(selector, element.form);
              fields.data('being_validated', true);
              fields.validate();
              fields.data('being_validated', false);
          }
          return valid;
      //Adjusted message
      }, jQuery.format("Please either skip these fields or only fill {0} of them."));
      

      完整的实现如下所示:

          $('#advancedSearchForm').validate({
          errorLabelContainer: '#advancedErrors',
          rules: {
              FirstName: {
                  require_from_group: [1, '.mygroup']
              },
              LastName: {
                  require_from_group: [1, '.mygroup']
              },
              countryCodeAdvanced: {
                  skip_or_fill_only_x: [1, '.location2']
              },
              location: {
                  skip_or_fill_only_x: [1, '.location2']
              },
              PositionTitle: {
                  skip_or_fill_only_x: [1, '.location2']
              },
              FunctionalArea: {
                  skip_or_fill_only_x: [1, '.location2']
              }
          },
          groups: {
              mygroup: "FirstName LastName",
              location2: "countryCodeAdvanced location PositionTitle FunctionalArea"
          }
      });
      
      
      jQuery.validator.addMethod("skip_or_fill_only_x", function (value, element, options) {
          var numberRequired = options[0];
          var selector = options[1];
          var numberFilled = $(selector, element.form).filter(function () {
              return $(this).val();
          }).length;
          var valid = numberFilled === numberRequired || numberFilled === 0;
          if (!$(element).data('being_validated')) {
              var fields = $(selector, element.form);
              fields.data('being_validated', true);
              fields.validate();
              fields.data('being_validated', false);
          }
          return valid;
      }, jQuery.format("Please either skip these fields or only fill {0} of them."));
      

      【讨论】:

        猜你喜欢
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-05
        • 2021-09-11
        • 2011-07-21
        • 2017-03-12
        相关资源
        最近更新 更多