J'utilise l'excellent plug-in jQuery Validate pour valider certains formulaires. Sur un formulaire, je dois m'assurer que l'utilisateur remplit au moins l'un d'un groupe de champs. Je pense que j'ai une assez bonne solution et je voulais la partager. Veuillez suggérer les améliorations auxquelles vous pourriez penser.
Ne trouvant aucun moyen intégré de le faire, j'ai recherché et trouvé la méthode de validation personnalisée de Rebecca Murphey , ce qui était très utile.
J'ai amélioré cela de trois manières:
- Pour vous laisser passer un sélecteur pour le groupe de champs
- Pour vous permettre de spécifier combien de ce groupe doit être rempli pour que la validation réussisse
- Pour afficher toutes les entrées du groupe comme ayant réussi la validation dès que l'une d'elles réussit la validation. (Voir le cri à Nick Craver à la fin.)
Vous pouvez donc dire "au moins X entrées correspondant au sélecteur Y doivent être renseignées".
Le résultat final, avec un balisage comme celui-ci:
<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">
... est un groupe de règles comme celui-ci:
// 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"]
}
L'élément n ° 3 suppose que vous ajoutez une classe de .checked
à vos messages d'erreur après une validation réussie. Vous pouvez le faire comme suit, comme illustré ici .
success: function(label) {
label.html(" ").addClass("checked");
}
Comme dans la démo liée ci-dessus, j'utilise CSS pour donner à chaque span.error
image X comme arrière-plan, à moins qu'elle n'ait la classe .checked
, auquel cas elle obtient une image de coche.
Voici mon code pour l'instant:
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."));
Hourra!
Hurler
Maintenant, pour ce cri - à l'origine, mon code cachait aveuglément les messages d'erreur sur les autres champs correspondants au lieu de les revalider, ce qui signifiait que s'il y avait un autre problème (comme `` seuls les nombres sont autorisés et vous avez entré des lettres '') , il a été masqué jusqu'à ce que l'utilisateur tente de soumettre. C'était parce que je ne savais pas comment éviter la boucle de rétroaction mentionnée dans les commentaires ci-dessus. Je savais qu'il devait y avoir un moyen, alors j'ai posé une question et Nick Craver m'a éclairé. Merci Nick!
Question résolue
C'était à l'origine une question «laissez-moi partager ceci et voir si quelqu'un peut suggérer des améliorations». Bien que j'apprécie toujours les commentaires, je pense qu'ils sont assez complets à ce stade. (Cela pourrait être plus court, mais je veux que ce soit facile à lire et pas nécessairement concis.) Alors profitez-en!
Mise à jour - fait désormais partie de jQuery Validation
Cela a été officiellement ajouté à jQuery Validation le 4/3/2012.
la source
Réponses:
C'est une excellente solution Nathan. Merci beaucoup.
Voici un moyen de faire fonctionner le code ci-dessus, au cas où quelqu'un aurait du mal à l'intégrer, comme je l'ai fait:
Code dans le fichier additional-methods.js :
Code à l'intérieur du fichier html :
N'oubliez pas d'inclure le fichier additional-methods.js!
la source
require_from_group: [1,".partnumber"]
et...[1,".contactname"]
s'assurer que vous validez les bonnes choses.Belle solution. Cependant, j'ai eu le problème d'autres règles obligatoires qui ne fonctionnaient pas. L'exécution de .valid () sur le formulaire a résolu ce problème pour moi.
la source
validator.formSubmit = true
. Dans la méthode require-from-group, je vérifie ensuite cet indicateur; si c'est là, je le fais$(element.form).valid();
, sinon je le faisfields.valid();
.Merci sean. Cela a résolu le problème que j'avais avec le code ignorant les autres règles.
J'ai également apporté quelques modifications afin que le message «Veuillez remplir au moins 1 champ ..» s'affiche dans un div distinct au lieu de chaque champ après tout.
mettre en forme valider le script
ajoutez ceci quelque part dans la page
ajouter à la méthode require_from_group fonction addMethod
la source
J'ai soumis un correctif qui ne souffre pas des problèmes de la version actuelle (par lequel l'option "requis" cesse de fonctionner correctement sur d'autres champs, une discussion des problèmes avec la version actuelle est sur github .
Exemple sur http://jsfiddle.net/f887W/10/
la source
Commencer un nom de variable avec $ est requis en PHP, mais assez bizarre (IMHO) en Javascript. De plus, je crois que vous l'appelez deux fois "$ module" et "module" une fois, non? Il semble que ce code ne devrait pas fonctionner.
De plus, je ne suis pas sûr que ce soit la syntaxe normale du plugin jQuery, mais je pourrais ajouter des commentaires au-dessus de votre appel addMethod, expliquant ce que vous accomplissez. Même avec votre description textuelle ci-dessus, il est difficile de suivre le code, car je ne sais pas à quel jeu de champs,: rempli, valeur, élément ou sélecteur fait référence. Peut-être que la plupart de cela est évident pour quelqu'un qui connaît le plugin Validate, alors faites preuve de jugement pour savoir quelle est la bonne quantité d'explications.
Vous pourriez peut-être sortir quelques variables pour auto-documenter le code; comme,
(en supposant que j'ai compris la signification de ces morceaux de votre code! :))
Je ne sais pas exactement ce que signifie "module", en fait - y a-t-il un nom plus spécifique que vous pourriez donner à cette variable?
Beau code, dans l'ensemble!
la source
Parce que le formulaire sur lequel je travaille a plusieurs régions clonées avec des entrées groupées comme celles-ci, j'ai passé un argument supplémentaire au constructeur require_from_group, en changeant exactement une ligne de votre fonction addMethod:
et de cette façon, un sélecteur, un ID ou un nom d'élément peut être passé une fois:
et le validateur limitera la validation aux éléments avec cette classe uniquement à l'intérieur de chaque fieldset, plutôt que d'essayer de compter tous les éléments classés .reqgrp dans le formulaire.
la source
Voici ma réponse à la réponse de Rocket Hazmat, en essayant de résoudre le problème des autres champs définis qui doivent également être validés, mais en marquant tous les champs comme valides lors du remplissage réussi de l'un.
Le seul problème restant avec cela maintenant est le cas limite où le champ est vide, puis rempli, puis à nouveau vide ... auquel cas l'erreur sera appliquée au champ unique et non au groupe. Mais cela semble si peu probable que cela se produise avec une fréquence quelconque et cela fonctionne toujours techniquement dans ce cas.
la source
J'avais des problèmes avec d'autres règles qui n'étaient pas vérifiées en conjonction avec cela, alors j'ai changé:
Pour ça:
J'ai également apporté quelques améliorations (personnelles), et voici la version que j'utilise:
la source
Merci, Nathan. Vous m'avez sauvé une tonne de temps.
Cependant, je dois remarquer que cette règle n'est pas prête pour jQuery.noConflict (). Donc, il faut remplacer tout $ par jQuery pour travailler avec, disons,
var $j = jQuery.noConflict()
Et j'ai une question: comment le faire se comporter comme une règle intégrée? Par exemple, si je saisis un e-mail, le message "Veuillez saisir un e-mail valide" disparaît automatiquement mais si je remplis l'un des champs du groupe, le message d'erreur reste.
la source