3

少なくとも1つのフィールドに入力する必要があり、すべての入力は整数または小数である必要があるフォームを作成しています。jqueryの検証プラグインを使用して検証しています。ここで見つけたものを作り直しましたが、部分的にはうまくいくようです。今私は持っています:

<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>

現在、検証には2つの問題があります。すべてのフィールドを空白のままにすると、1つだけ必要なときに3つのエラーメッセージが表示されます。

また、入力の1つに文字を入力すると、「数字のみ」のエラーメッセージが一瞬表示されますが、少なくとも1つのフィールドに入力するという2回目のテストで、入力がないことを補うため、フォームは送信されます。数字。

私はこれを完全に間違った方法で行っていますか?ここやjqueryフォーラムで見つけることができる例はどれも正確に適合していないようです。これを解決するには、どの方向に進むべきですか?

4

2 に答える 2

4

解決策を見つけたようです。コード内のコメントを参照してください。ライブデモ

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"
  });
});
于 2012-05-04T18:38:38.767 に答える
1

2つの問題があります。

  1. 数字のチェックに失敗しても、フォームの送信が妨げられることはありません。メッセージは表示されますが、送信されます。
  2. 3つのフィールドのいずれも存在しない場合、エラーメッセージが3回表示されます。

ここで開始状態を確認できます:http://jsfiddle.net/jclark/NR29t/1/ ; 私が変更した唯一のことは、フォームを送信する代わりに、フォームが送信されたときにアラートを発行するようになったことです。

これらを一度に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」ロジックは、無限チェーン(要素1が要素2を再検証し、要素1を無限に再検証する)を防ぎますが、これは、各フィールドがチェックされるときに、グループ形式のすべてのフィールドを再検証することを意味します。この再検証が問題を引き起こしているようです。最初のフィールドが数字以外の場合、そのエラーが記録されますが、最後のフィールドが検証されると、フォーム全体が再検証されますが、skip-inifite-loopチェックにより、他のフィールドがスキップされます。

私はそれが正しいと約98%確信しています。ただし、そのブロックを削除すると問題が解決することは知っています。このバージョンを参照してください:

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

さて、2番目の問題です。フィールド上のすべてのエラーを表示する動作は設計によるものであり、通常は理にかなっています。フィールドのグループがこのように相互に関連しているわけではありません。幸い、Validatorにはgroups、最初に見つかったエラーのみを報告するフィールドのグループを示すオプションがあります。このバージョンを参照してください:

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

フィールドに入力せずに送信すると、メッセージが1つだけ表示されます。ただし、新しい問題があります。「数字のみを入力してください」というメッセージは、無効な入力を残した直後、またはフィールドがフォーカスされている場合にのみ表示されます。これはバリデーターのバグだと思います。このスタックオーバーフローの質問を参照してください: jqueryvalidate-グループとそのラベル。具体的には、入力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"));

それは機能しますが、私はそれが好きではありません。数字チェックを再実装する必要があります。同じことをする必要がある他の検証チェックがある場合。

お役に立てれば。

于 2012-05-04T19:00:39.117 に答える