jquery表单验证需要一组输入中的一个并且要求输入是整数

时间:2012-05-01 21:16:07

标签: javascript jquery validation input

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

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

我是以完全错误的方式做这件事的吗?我在这里或在jquery论坛上找到的所有例子似乎都不合适。我应该朝哪个方向解决这个问题?

2 个答案:

答案 0 :(得分:4)

我似乎找到了解决方案。请参阅代码中的注释。 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"
  });
});

答案 1 :(得分:1)

你有两个问题:

  1. 数字检查失败并不会阻止表单提交 - 您会看到该消息,但随后会提交。
  2. 如果三个字段都不存在,则会收到错误消息三次。
  3. 您可以在此处查看起始状态: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”逻辑阻止了一个无限链(其中元素一重新验证了元素二,它重新验证了元素一,无限制),但是,这仍然意味着在检查每个字段时,它将重新验证组表单中的所有字段。看起来这个重新验证导致了问题。我认为发生的事情是,如果第一个字段是非数字的,则记录该错误,但是当验证最后一个字段时,它会重新验证整个表单,但跳过 - 无效循环检查会导致跳过其他字段;由于最后一个字段有效,整个表单都会提交。

    我大约98%肯定我有这个权利。但是,我知道删除该块可以消除这个问题。看到这个版本:

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

    现在是第二个问题。在场上显示所有错误的行为是设计的,通常是有意义的 - 只是不是一组字段是相互关联的。幸运的是,Validator提供了groups选项,用于表示只应报告找到的第一个错误的一组字段。看到这个版本:

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

    提交时未填写任何字段,您只能看到一条消息。但是,存在一个新问题:“请仅输入数字”消息仅在您输入无效输入后立即显示,或者当该字段被聚焦时。我认为这是一个Validator错误;请参阅此Stack Overflow问题: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"));
    

    它有效,但我不喜欢它;它需要重新执行数字检查;你还需要进行其他验证检查。

    希望这有帮助。