AngularJS: Ändert automatisch Modelländerungen

103

Angenommen, ich wollte so etwas wie automatisch Code ausführen (z. B. Daten auf einem Server speichern), wenn sich die Werte eines Modells ändern. Ist die einzige Möglichkeit, dies zu tun, indem Sie ng-changefür jedes Steuerelement etwas festlegen, das möglicherweise das Modell ändern könnte?

Das heißt, mit Ansichten ändern sich die Dinge richtig, wenn das Modell geändert wird, ohne dass explizit etwas angeschlossen werden muss. Gibt es ein Analogon zur Ausführung von Code, der auf einem Server gespeichert wird? Etwas wie

myModel.on('change', function() {
  $.post("/my-url", ...);
});

wie Sie vielleicht mit so etwas wie Rückgrat sehen.

Alec
quelle

Antworten:

151

In Ansichten mit {{}}und / oder ng-Modell richtet Angular $watch()es hinter den Kulissen für Sie ein.

Standardmäßig $watchwird als Referenz verglichen. Wenn Sie den dritten Parameter einstellen $watchzu true, Angular wird stattdessen „flach“ sehen Sie das Objekt für Änderungen. Für Arrays bedeutet dies, die Array-Elemente zu vergleichen, für Objektzuordnungen bedeutet dies, die Eigenschaften zu überwachen. Das sollte also tun, was Sie wollen:

$scope.$watch('myModel', function() { ... }, true);

Update : Angular v1.2 hat eine neue Methode hinzugefügt: `$ watchCollection () :

$scope.$watchCollection('myModel', function() { ... });

Beachten Sie, dass das Wort "flach" eher zur Beschreibung des Vergleichs als "tief" verwendet wird, da Referenzen nicht befolgt werden. Wenn das überwachte Objekt beispielsweise einen Eigenschaftswert enthält, der auf ein anderes Objekt verweist, wird diese Referenz zum Vergleich nicht befolgt das andere Objekt.

Mark Rajcok
quelle
1
Ah gut! Gibt es einen Grund, warum dies nicht so dokumentiert zu sein scheint (dh ich glaube nicht, dass in einem der Tutorials auf der eckigen Site $ watchs direkt eingerichtet wurde)? Gibt es etwas Schlechtes daran, das das Einrichten von (möglicherweise mehreren) ng-changeHooks an Eingabesteuerelementen zu einer besseren Idee machen würde?
Alec
12
Ja, es wäre schön, wenn im Haupt-Tutorial $ watch irgendwo erwähnt würde. Was an diesem Ansatz "schlecht" ist, ist, dass es zeitaufwändig sein kann, wenn Ihr Modell groß ist (jeder Digest-Zyklus - jeder Tastendruck in einem Eingabefeld - führt dazu, dass dieses Modell möglicherweise mehrfach einer gründlichen Schmutzprüfung unterzogen wird). . In diesem Fall wären selektive $ watch () es oder selektive ng-change besser.
Mark Rajcok
8

Wenn Sie Ihre Formularelemente entsprechend ihrem Status (geändert / nicht geändert) dynamisch formatieren oder testen müssen, ob sich einige Werte tatsächlich geändert haben, können Sie das folgende von mir entwickelte Modul verwenden: https://github.com/betsol / Winkeleingabe modifiziert

Es fügt dem Formular und seinen untergeordneten Elementen zusätzliche Eigenschaften und Methoden hinzu. Mit ihm können Sie testen, ob ein Element neue Daten enthält, oder sogar testen, ob das gesamte Formular neue nicht gespeicherte Daten enthält.

Sie können die folgende Überwachung einrichten: $scope.$watch('myForm.modified', handler)und Ihr Handler wird aufgerufen, wenn einige Formularelemente tatsächlich neue Daten enthalten oder wenn sie in den Ausgangszustand zurückkehren.

Sie können auch die modifiedEigenschaft einzelner Formularelemente verwenden, um die Datenmenge zu reduzieren, die über einen AJAX-Aufruf an einen Server gesendet wird. Es ist nicht erforderlich, unveränderte Daten zu senden.

Als Bonus können Sie Ihr Formular per Aufruf der Formularmethode in den Ausgangszustand reset()zurückversetzen.

Die Demo des Moduls finden Sie hier: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Prost!

Slava Fomin II
quelle
Gibt es eine Möglichkeit, dies in der Steuerung zu überprüfen? Wenn ich zum Beispiel auf die Schaltfläche x klicke, kann ich dann ein Popup zur Bestätigung von if (myform.modified) anzeigen?
Flash
Übergeben Sie FormController natürlich einfach an die Funktion Ihres Controllers: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Slava Fomin II
danke das wird nur etwas bewirken wenn das formular geändert wurde oder?
Flash
Dies geht FormControllerauf die doSomething()Funktion Ihres Controllers über. Innerhalb dieser Funktion können Sie alles tun, was Sie wollen, z. B. überprüfen Sie, ob das Formular tatsächlich geändert wurde, indem Sie die FormController.modifiedboolesche Eigenschaft überprüfen .
Slava Fomin II
Vielen Dank! Nettes Feature
Flash