Comment écrire une directive angulaire pour un scénario «Obligatoire si»?

Je travaille à comprendre comment utiliser les directives angulaires pour implémenter des validations frontales. Bien que je connaisse bien la façon dont les directives fonctionnent généralement, ce que j'ai de la difficulté à trouver dans n'importe quel tutoriel, blogpost, ou même les documents angulaires réels, est de savoir comment implémenter une validation utile. (Par là, je veux dire un qui n'est pas déjà là, comme dans ce tutoriel de base pour la mise en œuvre d'un attribut de validation .

La plus courante d'entre eux, selon mon expérience, est un scénario «requis». Si j'ai le champ de texte A et le champ de texte B dans ma forme, et que le champ de texte A a une valeur, mes règles commerciales me disent que le champ de texte B doit avoir une valeur. Toutefois, les différents didacticiels pour les directives de validation ne sont tous basés sur l'élément auquel ils sont liés.

Question: Je soupçonne que je suis en train d'aborder le problème de la mise en œuvre de quelque chose comme une validation requise si la validation est complètement erronée. De manière angulaire, quelle est la manière correcte d'exiger une valeur sous une forme si et seulement si un champ dont elle dépend est une valeur?

Vous pouvez essayer d'utiliser ng-if pour ajouter l'élément de formulaire suivant uniquement si l'élément de formulaire précédent est valide. Le second élément n'existera pas dans le DOM, sauf si le premier élément est valide.

J'ai fait des expérimentations supplémentaires aujourd'hui. Un collègue m'a incité avec une situation différente, qui m'a finalement conduit à résoudre le problème pour moi-même.

Je regardais fondamentalement le problème de manière erronée, pour les débutants – en particulier, je l'ai examiné de la manière jQuery, en attendant la directive d'exposer de quelque façon des moyens de lire des éléments de forme individuels. Ce n'est pas nécessairement correct, car nous avons une portée que nous pouvons évaluer.

Voici le code pré-1.3 Code angulaire:

var app = angular.module('app', []); app.controller('someController', [ '$scope', function($scope) { $scope.valueA = ''; $scope.valueB = 'Chicken'; } ]); app.directive('requiredIf', [ function () { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attr, model) { // Read the companion attribute 'otherModelName' var otherModelName = attr.otherModelName; scope.$watch(attr.ngModel, function (value) { var isValid = checkAgainstDependentModel(value); model.$setValidity('requiredIf', isValid); }); function checkAgainstDependentModel(value) { // Assumes that the scope exposes a property with the passed-in // model name as its name var field = scope[otherModelName]; var isValid = true; if(field != null || field != '') if(value == null || value == '') isValid = false; return isValid; } } }; } ]); 

… Dans le marquage, nous l'utiliserions comme suit:

 <form name='someForm'> <input type='text' name='mainField' ng-model='valueA' /> <input type='text' name='subordinateField' ng-model='valueB' required-if other-model-name='valueA' /> <span style='color=red' ng-if='someForm.subordinateField.$error.requiredIf'> (Required!) </span> </form> 

Ce modèle peut être étendu à diverses autres validations personnalisées, pré-1.3. Mes recherches m'ont montré que Angular 1.3 supprime les $parsers et $formatters en faveur de $validators et $asyncValidators .

EDIT: Au lieu d'utiliser $formatters/$parsers , une meilleure idée que j'ai rencontrée est de faire une scope.$watch le ngModel associé. Comme il s'agit d'une implémentation avant 1,3, nous pouvons encore faire un model.$setValidity('thing', isValid); Ceci est basé sur la réponse à la question de la meilleure façon d'obtenir la validation à distance pré-1.3 .