Wie überprüfe ich die Formulargültigkeit innerhalb eines Watchers korrekt, wenn Modelldaten außerhalb des Formulars in AngularJS geändert werden?

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

Frage

Ich bin noch recht neu bei AngularJS und glaube, ich habe Probleme, das Timing mit $scope zu verstehen.In einem Controller habe ich einen Watcher für einige Modelldaten eingerichtet, die an verschiedene Formularelemente gebunden sind.Der Watcher löst eine Ajax-Anfrage aus, wenn sich die Daten ändern, es sei denn, das Formular ist ungültig.Ich überprüfe die Formulargültigkeit mit myForm.$valid.Das ist jedoch alles ziemlich einfach, außer wenn die Modelldaten im Controller aktualisiert werden und nicht das Formular.Die Validierungen werden wie erwartet ausgeführt, aber form.$valid hat immer noch den vorherigen Wert und nicht den Wert, der mit den aktualisierten Daten sein sollte.Wenn das Formular beispielsweise zuvor gültig war, lösche ich den an eine erforderliche Eingabe gebundenen Modellwert. Der Watcher wird ausgelöst, weil sich die Modelldaten geändert haben. Wenn ich jedoch den Wert von myForm.$valid protokolliere, ist sein Wert immer noch wahr. auch wenn es falsch sein sollte.

Meine Frage ist also A.Warum passiert das?, aber was noch wichtiger ist: B.Wie gehe ich richtig mit dem um, was ich erreichen möchte?Wäre eine benutzerdefinierte Richtlinie sinnvoll?

Hier ist ein vereinfachtes Beispiel.

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>

Regler:

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';
        }
    });
}]);

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

War es hilfreich?

Lösung

Eine benutzerdefinierte Direktive ist der richtige Weg.Aus mehreren Gründen wird im Allgemeinen empfohlen, Überwachungen in Anweisungen und Controllern zu platzieren.Ein Grund dafür ist auf hoher Ebene, dass Angular empfiehlt, dass Controller dünn sind und nur als Bindeglied zwischen der Ansicht und den Diensten fungieren.Aber Sie treffen auf einen bestimmten, interessanten Grund.

Controller werden ausgeführt, bevor Angular-Anweisungen eingebunden werden.Ihre Controller-Uhr wird also vor der von Angular zur Beobachtungsliste hinzugefügt ngModelWatch() tut für myData. ngModelWatch() Hier läuft Angular $formatters (Ich erinnere mich daran $formatters, (unter anderem dort, wo die Validierung ausgelöst wird, wenn eine Änderung am Modell auftritt).

Da Uhren in der Reihenfolge ausgeführt werden, in der sie zur Beobachtungsliste hinzugefügt wurden, ist Ihr Regler $watch wird vor der Validierung ausgeführt wird erledigt von $formatters.

Wenn Sie stattdessen das Gleiche setzen $watch Innerhalb einer Direktive wird es beim anschließenden Link hinzugefügt ngModelWatch() wurde zur Merkliste hinzugefügt.Daher der Richtlinie $watch wird nach der Validierung ausgeführt erledigt.

Hier ist eine aktualisierte Geige wo Sie die Reihenfolge der Ausführung sehen können $formatters und jede $watch.Und Sie werden sehen, dass die Direktivenversion wie erwartet funktioniert – sie wird danach ausgeführt $formatters.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top