【问题标题】:jquery form validation require one of a group of inputs AND require that input is an integerjquery表单验证需要一组输入中的一个并且要求输入是一个整数
【发布时间】:2012-05-01 21:16:07
【问题描述】:

我正在制作一个需要填写至少一个字段并且所有输入必须是整数或小数的表单。我正在使用 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 条错误消息!

另外,如果我在其中一个输入中输入一个字母,我会得到一秒钟的“仅限数字”错误消息,但表单仍然提交,因为至少填写 1 个字段的第二次测试弥补了因为没有数字。

我这样做是否完全错误?我在这里或 jquery 论坛上找不到的示例似乎都不完全适合。我应该从哪个方向解决这个问题?

【问题讨论】:

  • 为了 Web 开发中的一切神圣,请在您的表单中使用&lt;label for="input-id-name"&gt;;它使表单更易于访问和用户友好。
  • 哦,我会这样做,这是一个很好的点,我只是想让 js 先工作,然后我想我会设置标签、占位符等。
  • 别担心,我也没有使用这些丑陋的表格,我现在只是这样写的,一旦我弄清楚如何让错误显示出来,我打算修复它。
  • 你应该奖励其中一个答案。

标签: javascript jquery validation input


【解决方案1】:

看来我找到了解决办法。请参阅代码中的 cmets。 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"
  });
});

【讨论】:

    【解决方案2】:

    你有两个问题:

    1. 未通过数字检查不会阻止表单提交 - 您会看到消息,但随后会提交。
    2. 如果三个字段都不存在,您会收到三次错误消息。

    这里可以看到开始状态: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”逻辑阻止了无限链(其中元素一重新验证元素二,它重新验证元素一,无限期),但是,这仍然意味着当每个字段被检查时,它将重新验证组表单中的所有字段。看起来这种重新验证导致了问题。我认为正在发生的事情是,如果第一个字段不是数字,则会记录该错误,但是当验证最后一个字段时,它会重新验证整个表单,但是 skip-inifite-loop 检查会导致其他字段被跳过;由于最后一个字段有效,因此整个表单都提交了。

    我有 98% 的把握我做对了。但是,我确实知道删除该块可以解决问题。看到这个版本:

    http://jsfiddle.net/jclark/NR29t/2/

    现在是第二期。在字段上显示所有错误的行为是设计使然,并且通常是有意义的——只是不是一组字段像这样相互关联。幸运的是,Validator 提供了groups 选项,表示一组字段,它们应该只报告发现的第一个错误。看到这个版本:

    http://jsfiddle.net/jclark/NR29t/3/

    提交时未填写任何字段,您只会看到一条消息。但是,有一个新问题:“请仅输入数字”消息仅在您留下无效输入或该字段获得焦点后立即显示。我认为这是一个验证器错误;看到这个堆栈溢出问题: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"));
    

    它有效,但我不喜欢它;它需要重新实现数字检查;如果您有其他验证检查需要做同样的事情。

    希望这会有所帮助。

    【讨论】:

    • 杰森感谢您提供的信息,我希望我可以在你们俩之间分配赏金,这样会更公平!我很感激!
    猜你喜欢
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2014-12-09
    • 2017-04-07
    相关资源
    最近更新 更多