AngularJS: automatycznie wykrywa zmianę w modelu

103

Załóżmy, że chciałem zrobić coś takiego, jak automatyczne uruchamianie kodu (np. Zapisywanie danych na serwerze) za każdym razem, gdy zmienią się wartości modelu. Czy jest to jedyny sposób, aby to zrobić, ustawiając coś podobnego ng-changena każdej kontrolce, która mogłaby zmienić model?

Oznacza to, że w przypadku widoków rzeczy zmieniają się tak, jak zmienia się model, bez konieczności jawnego podłączania czegokolwiek. Czy istnieje analogia do możliwości uruchamiania kodu, który zapisuje na serwerze? Coś jak

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

jak możesz zobaczyć z czymś w rodzaju kręgosłupa.

Alec
źródło

Odpowiedzi:

151

W widokach z {{}}i / lub ng-model, Angular konfiguruje $watch()dla Ciebie za kulisami.

Domyślnie $watchporównuje przez odniesienie. Jeśli trzeci parametr ustawiony $watchna truekątowa będzie zamiast „płytkie” oglądanie obiektu dla zmian. W przypadku tablic oznacza to porównywanie elementów tablicy, w przypadku map obiektów oznacza to obserwowanie właściwości. Więc powinno to zrobić, co chcesz:

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

Aktualizacja : Angular v1.2 dodał do tego nową metodę, `$ watchCollection () :

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

Zwróć uwagę, że do opisu porównania używa się słowa „płytkie”, a nie „głębokie”, ponieważ nie stosuje się odniesień - np. Jeśli obserwowany obiekt zawiera wartość właściwości, która jest odniesieniem do innego obiektu, odniesienie to nie jest stosowane w celu porównania inny obiekt.

Mark Rajcok
źródło
1
Ach, świetnie! Czy jest jakiś powód, dla którego wydaje się, że to nie wszystko jest udokumentowane (tj. Nie sądzę, aby w żadnym z tutoriali na stronie kątowej wspomniano o bezpośrednim ustawianiu zegarków $)? Czy jest w tym coś złego, co sprawiłoby, że ustawienie (potencjalnie wielu) ng-changepunktów zaczepienia na kontrolkach wejściowych byłoby lepszym pomysłem?
Alec
12
Tak, byłoby miło, gdyby główny tutorial gdzieś wspominał o $ watch. To, co jest „złe” w tym podejściu, polega na tym, że może być czasochłonne, jeśli model jest duży (każdy cykl podsumowania - każde naciśnięcie klawisza w polu wejściowym - spowoduje, że ten model zostanie głęboko sprawdzony, prawdopodobnie wiele razy) . W takim przypadku selektywne $ watch () es lub selektywna zmiana ng byłyby lepsze.
Mark Rajcok
8

A jeśli chcesz stylizować elementy formularza zgodnie z ich stanem (zmodyfikowany / niezmodyfikowany) dynamicznie lub przetestować, czy niektóre wartości faktycznie się zmieniły, możesz użyć następującego modułu, opracowanego przeze mnie: https://github.com/betsol / kątowe wejście-zmodyfikowane

Dodaje dodatkowe właściwości i metody do formularza i jego elementów potomnych. Dzięki niemu możesz sprawdzić, czy jakiś element zawiera nowe dane, a nawet sprawdzić, czy cały formularz ma nowe niezapisane dane.

Możesz ustawić następujący watch: $scope.$watch('myForm.modified', handler)i twój program obsługi zostanie wywołany, jeśli jakieś elementy formularza faktycznie zawierają nowe dane lub jeśli został przywrócony do stanu początkowego.

Możesz również użyć modifiedwłaściwości poszczególnych elementów formularza, aby faktycznie zmniejszyć ilość danych wysyłanych do serwera za pośrednictwem wywołania AJAX. Nie ma potrzeby przesyłania niezmienionych danych.

Jako bonus możesz przywrócić swój formularz do stanu początkowego poprzez wywołanie reset()metody formularza .

Demo modułu można znaleźć tutaj: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Twoje zdrowie!

Slava Fomin II
źródło
Czy jest sposób, aby to sprawdzić w kontrolerze. na przykład po kliknięciu przycisku x czy mogę wyświetlić wyskakujące okienko potwierdzenia if (myform.modified)?
Flash
Oczywiście po prostu przekaż FormController do funkcji twojego kontrolera: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Slava Fomin II
dzieki to zrobi cos tylko jesli formularz byl zmodyfikowany tak?
Flash
To przejdzie FormControllerdo doSomething()funkcji twojego kontrolera. Możesz zrobić z nim cokolwiek chcesz w ramach tej funkcji, np. Sprawdzić, czy formularz został faktycznie zmodyfikowany, sprawdzając FormController.modifiedwłaściwość boolowską.
Slava Fomin II
Dzięki! Niezła funkcja
Flash