J'ai une table créée à l'aide de ng-repeat. Je souhaite ajouter une validation à chaque élément du tableau. Le problème est que chaque cellule d'entrée a le même nom que la cellule au-dessus et en dessous. J'ai essayé d'utiliser la {{$index}}
valeur pour nommer les entrées, mais bien que les littéraux de chaîne en HTML semblent corrects, cela fonctionne maintenant.
Voici mon code pour le moment:
<tr ng-repeat="r in model.BSM ">
<td>
<input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
</td>
</tr>
J'ai essayé de supprimer l' {{}}
index, mais cela ne fonctionne pas non plus. À partir de maintenant, la propriété de validation de l'entrée fonctionne correctement, mais le message d'erreur ne s'affiche pas.
Quelqu'un a des suggestions?
Edit: En plus des excellentes réponses ci-dessous, voici un article de blog qui couvre ce problème plus en détail: http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2 /
la source
Réponses:
AngularJS s'appuie sur les noms d'entrée pour exposer les erreurs de validation.
Malheureusement, à ce jour, il n'est pas possible (sans utiliser une directive personnalisée) de générer dynamiquement le nom d'une entrée. En effet, en vérifiant les documents d'entrée, nous pouvons voir que l'attribut name n'accepte qu'une chaîne.
Pour résoudre le problème du 'nom dynamique', vous devez créer un formulaire interne (voir ng-form ) :
L'autre alternative serait d'écrire une directive personnalisée pour cela.
Voici le jsFiddle montrant l'utilisation du ngForm: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/
la source
ng-form
des éléments DOM, donc le lien vers l'autre question SO n'est pas pertinent ici.ng-repeat
lié,table tr
vous devez utiliserng-form="myname"
attr.Depuis que la question a été posée, l'équipe Angular a résolu ce problème en permettant de créer dynamiquement des noms d'entrée.
Avec Angular version 1.3 et ultérieure, vous pouvez maintenant faire ceci:
Démo
Angular 1.3 a également introduit ngMessages, un outil plus puissant pour la validation de formulaire. Vous pouvez utiliser la même technique avec ngMessages:
la source
$valid
propriété de l'entrée est incorrectefalse
Si vous ne souhaitez pas utiliser ng-form, vous pouvez utiliser une directive personnalisée qui modifiera l'attribut de nom du formulaire. Placez cette directive en tant qu'attribut sur le même élément que votre ng-model.
Si vous utilisez d'autres directives en conjonction, veillez à ce qu'elles ne disposent pas de la propriété "terminal", sinon cette fonction ne pourra pas s'exécuter (étant donné qu'elle a une priorité de -1).
Par exemple, lorsque vous utilisez cette directive avec ng-options, vous devez exécuter ce monkeypatch d'une ligne: https://github.com/AlJohri/bower-angular/commit/eb17a967b7973eb7fc1124b024aa8b3ca540a155
Je trouve souvent utile d'utiliser ng-init pour définir $ index sur un nom de variable. Par exemple:
Cela change votre expression régulière en:
Si vous avez plusieurs ng-répétitions imbriquées, vous pouvez désormais utiliser ces noms de variables au lieu de $ parent. $ Index.
Définition du "terminal" et de la "priorité" pour les directives: https://docs.angularjs.org/api/ng/service/ $ compile # directive-definition-object
Commentaire de Github concernant le besoin de ng-option monkeypatch: https://github.com/angular/angular.js/commit/9ee2cdff44e7d496774b340de816344126c457b3#commitcomment-6832095 https://twitter.com/aljohri/status/4829146354
METTRE À JOUR:
Vous pouvez également faire fonctionner cela avec ng-form.
la source
Utilisez la directive ng-form à l'intérieur de la balise dans laquelle vous utilisez la directive ng-repeat. Vous pouvez ensuite utiliser la portée créée par la directive ng-form pour référencer un nom générique. Par exemple:
Crédit à: http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html
la source
ng-form="formName"
au tag qui a ng-repeat ... cela a fonctionné comme un charme :)Ajout d'un exemple plus complexe avec "validation personnalisée" du côté du contrôleur http://jsfiddle.net/82PX4/3/
la source
En examinant ces solutions, celle fournie par Al Johri ci-dessus est la plus proche de mes besoins, mais sa directive était un peu moins programmable que je ne le souhaitais. Voici ma version de ses solutions:
Cette solution vous permet simplement de passer une expression de générateur de nom à la directive et évite le verrouillage de la substitution de modèle qu'il utilisait.
J'ai également eu des problèmes au départ avec cette solution car elle ne montrait pas d'exemple d'utilisation dans le balisage, alors voici comment je l'ai utilisée.
J'ai un exemple de travail plus complet sur github .
la source
la validation fonctionne avec ng repeat si j'utilise la syntaxe suivante,
scope.step3Form['item[107][quantity]'].$touched
je ne sais pas que c'est une meilleure pratique ou la meilleure solution, mais cela fonctionnela source
En me basant sur la réponse de pkozlowski.opensource , j'ai ajouté un moyen d'avoir des noms d'entrée dynamiques qui fonctionnent également avec ngMessages . Notez la
ng-init
partie sur l'ng-form
élément et l'utilisation defurryName
.furryName
devient le nom de la variable contenant la valeur de la variable pour l' attributinput
sname
.la source
Il est trop tard mais peut-être que cela peut aider n'importe qui
fromname[uniquname].$error
Exemple de code:
Voir la démo de travail ici
la source
Si votre utilisation de ng-repeat $ index fonctionne comme ceci
et
nous devons montrer le ng-show dans ng-pattern
la source
C'est possible et voici comment je fais la même chose avec un tableau d'entrées.
envelopper la table dans une forme comme celle-ci
Alors utilisez simplement ceci
J'ai un formulaire avec des directives multi-imbriquées qui contiennent toutes des entrées, des sélections, etc. Ces éléments sont tous entourés de ng-repeats et de valeurs de chaîne dynamiques.
Voici comment utiliser la directive:
Remarque: vous pouvez ajouter et indexer la concaténation de chaînes si vous avez besoin de sérialiser peut-être une table d'entrées; c'est ce que j'ai fait.
Cela devrait gérer de nombreuses situations où vous ne savez tout simplement pas où le formulaire sera. Ou peut-être avez-vous des formulaires imbriqués, mais pour une raison quelconque, vous souhaitez attacher ce nom d'entrée à deux formulaires? Eh bien, transmettez simplement le nom du formulaire auquel vous souhaitez attacher le nom d'entrée.
Ce que je voulais, c'était un moyen d'attribuer des valeurs dynamiques à des entrées que je ne saurais jamais, puis d'appeler simplement $ scope.myFormName. $ Valid.
Vous pouvez ajouter tout ce que vous souhaitez: plus de tables, plus d'entrées de formulaire, des formulaires imbriqués, tout ce que vous voulez. Passez simplement le nom du formulaire sur lequel vous souhaitez valider les entrées. Ensuite, lors de l'envoi du formulaire, demandez si le $ scope.yourFormName. $ Valid
la source
Cela obtiendra le nom dans le ng-repeat pour apparaître séparément dans la validation du formulaire.
Mais j'ai eu du mal à le faire rechercher dans son message de validation, j'ai donc dû utiliser un ng-init pour lui faire résoudre une variable en tant que clé d'objet.
la source
Voici un exemple de comment je fais cela, je ne sais pas si c'est la meilleure solution, mais fonctionne parfaitement.
Tout d'abord, du code en HTML. Regardez ng-class, il appelle la fonction hasError. Regardez également la déclaration de nom de l'entrée. J'utilise $ index pour créer différents noms d'entrée.
Et maintenant, voici la fonction hasError:
la source
Mes exigences étaient un peu différentes de celles posées sur la question initiale, mais j'espère que je pourrais aider quelqu'un qui traverse le même problème que moi.
Je devais définir si un champ était requis ou non en fonction d'une variable de portée. Donc, je devais essentiellement définir
ng-required="myScopeVariable"
(qui est une variable booléenne).la source