いくつかのフォームを検証するために、優れたjQueryValidateプラグインを使用しています。1つのフォームで、ユーザーがフィールドのグループの少なくとも1つに入力するようにする必要があります。私はかなり良い解決策を持っていると思います、そしてそれを共有したかったです。 考えられる改善点を提案してください。
これを行うための組み込みの方法が見つからなかったので、 Rebecca Murpheyのカスタム検証方法を検索して見つけました。これは、非常に役に立ちました。
私はこれを3つの方法で改善しました:
- フィールドのグループのセレクターを渡すことができます
- 検証に合格するためにそのグループのいくつを埋める必要があるかを指定できるようにするには
- グループ内のすべての入力を、そのうちの1つが検証に合格するとすぐに、検証に合格したものとして表示します。(最後にニック・クレイバーへの叫び声を参照してください。)
したがって、 「セレクターYに一致する少なくともX個の入力を入力する必要があります」と言うことができます。
次のようなマークアップを使用した最終結果:
<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"]
}
.checked
項目3は、検証が成功したときにエラーメッセージにクラスを追加することを前提としています。ここに示すように、これは次のように実行できます。
success: function(label) {
label.html(" ").addClass("checked");
}
上にリンクされたデモのように、クラスがない限り、CSSを使用して各span.error
X画像を背景として指定します。クラスがない.checked
場合は、チェックマーク画像が取得されます。
これまでの私のコードは次のとおりです。
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."));
やったー!
大声で叫ぶ
さて、その叫び声のために-元々、私のコードは、他の一致するフィールドのエラーメッセージを再検証するのではなく、盲目的に隠しました。つまり、別の問題が発生した場合(「数字のみが許可され、文字を入力した」など) 、ユーザーが送信しようとするまで非表示になりました。これは、上記のコメントで言及されているフィードバックループを回避する方法がわからなかったためです。方法があるはずだとわかっていたので、質問をしたところ、ニック・クレイバーが教えてくれました。ありがとう、ニック!
質問が解決しました
これはもともと「これを共有して、誰かが改善を提案できるかどうかを確認させてください」という種類の質問でした。フィードバックは歓迎しますが、現時点ではかなり完了していると思います。(もっと短くてもかまいませんが、読みやすく、必ずしも簡潔ではないようにしたいと思います。)だから楽しんでください!
更新-jQuery検証の一部になりました
これは、2012年4月3日にjQuery検証に正式に追加されました。