Comment vérifier correctement la validité du formulaire au sein d'un observateur lorsque les données du modèle sont modifiées en dehors du formulaire dans angulairejs ?

StackOverflow https://stackoverflow.com//questions/21034489

Question

Je suis encore assez nouveau sur AngularJS et je pense que j'ai du mal à comprendre le timing avec $scope.Dans un contrôleur, j'ai configuré un observateur pour certaines données de modèle liées à divers éléments de formulaire.L'observateur déclenche une requête ajax lorsque les données changent, sauf si le formulaire n'est pas valide.Je vérifie la validité du formulaire avec myForm.$valid.Cependant, tout cela est assez simple, sauf lorsque les données du modèle sont mises à jour dans le contrôleur, et non dans le formulaire.Les validations s'exécutent comme prévu, mais form.$valid a toujours la valeur précédente, et non celle qu'elle devrait être avec les données mises à jour.Par exemple, si le formulaire était auparavant valide, alors je supprime la valeur du modèle liée à une entrée requise, l'observateur se déclenchera car les données du modèle ont changé, mais lorsque j'enregistre la valeur de myForm.$valid, sa valeur est toujours vraie, même si cela devrait être faux.

Ma question est donc A.pourquoi cela se produit-il ?, mais plus important encore, B.quelle est la bonne façon de gérer ce que j'essaie d'accomplir ?Une directive personnalisée aurait-elle un sens ?

Voici un exemple simplifié.

HTML :

<div ng-controller="MyCtrl">
    <form name="myForm">
        <input type="text" name="myField" ng-model="myData" required>
        <button type="button" ng-click="myData=''">Delete</button>
    </form>

    <div>
        The watcher says the form is: <strong>{{ formStatus }}</strong>    
    </div>
</div>

Manette:

myApp.controller('MyCtrl', ['$scope', function($scope) {
    $scope.myData = 'abc';
    $scope.formStatus = '';

    $scope.$watch('myData', function(newVal, oldVal) {
        if (newVal != oldVal) {
            console.log("my data changed");
            console.log("my form valid = ", $scope.myForm.$valid);        
            $scope.formStatus = $scope.myForm.$valid ? 'Valid' : 'Invalid';
        }
    });
}]);

Violon: http://jsfiddle.net/anpsince83/cK6cc/1/

Était-ce utile?

La solution

Une directive personnalisée est la bonne voie à suivre.Il est généralement recommandé, pour plusieurs raisons, que les montres soient placées dans des directives plutôt que dans des contrôleurs.À un niveau élevé, l'une des raisons est qu'Angular recommande que les contrôleurs soient minces et ne fonctionnent que comme un lien entre la vue et les services.Mais vous abordez une raison spécifique et intéressante.

Les contrôleurs s'exécutent avant que les directives angulaires ne soient liées.Ainsi, votre montre de contrôleur est ajoutée à la liste de surveillance avant celle d'Angular. ngModelWatch() fait pour myData. ngModelWatch() c'est là qu'Angular s'exécute $formatters (en rappelant que $formatters, entre autres choses, sont l'endroit où la validation est déclenchée lorsqu'une modification se produit dans le modèle).

Étant donné que les surveillances sont exécutées dans l'ordre dans lequel elles ont été ajoutées à la liste de surveillance, votre manette $watch s'exécute avant la validation étant fait par $formatters.

Si tu mets plutôt la même chose $watch à l'intérieur d'une directive, il sera ajouté lors du lien après ngModelWatch() a été ajouté à la liste de surveillance.Ainsi la directive $watch s'exécutera après validation est fait.

Voici un violon mis à jour où vous pouvez regarder l'ordre d'exécution de $formatters et chacun $watch.Et vous verrez que la version de la directive fonctionne comme prévu - s'exécutant après $formatters.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top