AngularJS: Automatische Erkennung von Modelländerungen

Lesezeit: 4 Minuten

Benutzer-Avatar
alecbz

Angenommen, ich wollte so etwas wie automatisch ausführen (wie das Speichern von Daten auf einem Server), wenn sich die Werte eines Modells ändern. Ist die einzige Möglichkeit, dies zu tun, indem Sie so etwas wie einstellen ng-change auf jeder Steuerung, die möglicherweise das Modell verändern könnte?

Das heißt, bei Ansichten ändern sich die Dinge direkt, wenn das Modell geändert wird, ohne dass explizit etwas angeschlossen werden muss. Gibt es eine Analogie 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 Backbone sehen.

Benutzer-Avatar
Markus Rajcok

In Ansichten mit {{}} und/oder ng-model, Angular wird eingerichtet $watch()es für Sie hinter den Kulissen.

Standardmäßig $watch vergleicht per Referenz. Wenn Sie den dritten Parameter auf setzen $watch zu true, Angular überwacht das Objekt stattdessen “flach” auf Änderungen. Für Arrays bedeutet dies, die Array-Elemente zu vergleichen, für Objektkarten bedeutet dies, die Eigenschaften zu beobachten. Das sollte also tun, was Sie wollen:

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

Aktualisieren: Angular v1.2 hat dafür eine neue Methode hinzugefügt, `$watchCollection():

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

Beachten Sie, dass das Wort “oberflächlich” verwendet wird, um den Vergleich zu beschreiben, und nicht “tief”, weil Referenzen nicht verfolgt werden — zB wenn das überwachte Objekt einen Eigenschaftswert enthält, der eine Referenz auf ein anderes Objekt ist, wird dieser Referenz nicht gefolgt, um zu vergleichen das andere Objekt.

  • Ah gut! Gibt es einen Grund, warum dies nicht so dokumentiert zu sein scheint (dh ich glaube nicht, dass eines der Tutorials auf der eckigen Website das direkte Einrichten von $watches erwähnt hat)? Gibt es etwas Schlechtes daran, das die Einrichtung (möglicherweise mehrerer) ng-change Haken bei Eingabesteuerelementen eine bessere Idee?

    – Alecbz

    15. März 2013 um 3:42 Uhr

  • Ja, es wäre schön, wenn das Haupt-Tutorial $watch irgendwo erwähnen würde. Das „Schlechte“ an diesem Ansatz ist, dass er zeitaufwändig sein kann, wenn Ihr Modell groß ist (jeder Digest-Zyklus – jeder Tastendruck in einem Eingabefeld – führt dazu, dass dieses Modell gründlich überprüft wird, möglicherweise mehrmals). . In diesem Fall wären selektive $watch()es oder selektive ng-Änderungen besser.

    – Markus Rajcok

    15. März 2013 um 3:57 Uhr

Und wenn Sie Ihre Formularelemente entsprechend ihrem Status (geändert/nicht geändert) dynamisch formatieren oder testen möchten, ob sich einige Werte tatsächlich geändert haben, können Sie das folgende von mir entwickelte Modul verwenden:
https://github.com/betsol/angular-input-modified

Es fügt dem Formular und seinen untergeordneten Elementen zusätzliche Eigenschaften und Methoden hinzu. Damit 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 Uhr einrichten: $scope.$watch('myForm.modified', handler) und Ihr Handler wird aufgerufen, wenn einige Formularelemente tatsächlich neue Daten enthalten oder in den ursprünglichen Zustand zurückgesetzt wurden.

Außerdem können Sie verwenden modified Eigenschaft einzelner Formularelemente, um die per AJAX-Aufruf an einen Server gesendete Datenmenge tatsächlich zu reduzieren. Es müssen keine unveränderten Daten gesendet werden.

Als Bonus können Sie Ihr Formular per Call-to-Forms in den ursprünglichen Zustand zurückversetzen reset() Methode.

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

Prost!

  • Gibt es eine Möglichkeit, dies in der Steuerung zu überprüfen. Wenn ich zum Beispiel auf die x-Schaltfläche klicke, kann ich ein if(myform.modified)-Bestätigungs-Popup anzeigen?

    – Blinken

    25. Mai 2017 um 19:05 Uhr

  • Natürlich übergeben Sie FormController einfach an die Funktion Ihres Controllers: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.

    – Slawa Fomin II

    26. Mai 2017 um 19:12 Uhr

  • danke, das wird nur etwas tun, wenn das Formular geändert wurde, oder?

    – Blinken

    31. Mai 2017 um 18:30 Uhr

  • Es wird vorübergehen FormController zum doSomething() Funktion Ihres Controllers. Sie können innerhalb dieser Funktion alles tun, was Sie wollen, z. B. überprüfen, ob das Formular tatsächlich geändert wurde, indem Sie das überprüfen FormController.modified boolesche Eigenschaft.

    – Slawa Fomin II

    31. Mai 2017 um 19:53 Uhr

  • Vielen Dank! Schöne Funktion

    – Blinken

    5. Juni 2017 um 20:50 Uhr

Erkennen Sie Änderungen in einem einzelnen Modell

$scope.$watchCollection('model1', function () {
    //...
}, true);

Erkennen Sie Änderungen in mehreren Modellen

$scope.$watchCollection('[model1, model2, model3]', function () {
    //...
}, true);

1205200cookie-checkAngularJS: Automatische Erkennung von Modelländerungen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy