AngularJS: rileva automaticamente il cambiamento nel modello


103

Supponiamo di voler fare qualcosa come eseguire automaticamente del codice (come salvare i dati su un server) ogni volta che i valori di un modello cambiano. L'unico modo per farlo è impostare qualcosa di simile ng-changesu ogni controllo che potrebbe alterare il modello?

Cioè, con le visualizzazioni, le cose cambiano proprio quando il modello viene modificato senza dover collegare esplicitamente nulla. Esiste un analogo alla possibilità di eseguire codice che salva su un server? Qualcosa di simile a

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

come potresti vedere con qualcosa come spina dorsale.

Risposte:


151

Nelle visualizzazioni con {{}}e / o ng-model, Angular ti sta allestendo $watch()dietro le quinte.

Per impostazione predefinita, $watchconfronta per riferimento. Se imposti il ​​terzo parametro su $watcha true, Angular guarderà invece "superficiale" l'oggetto per i cambiamenti. Per gli array questo significa confrontare gli elementi dell'array, per le mappe di oggetti significa osservare le proprietà. Quindi questo dovrebbe fare quello che vuoi:

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

Aggiornamento : Angular v1.2 ha aggiunto un nuovo metodo per questo, `$ watchCollection () :

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

Nota che la parola "superficiale" è usata per descrivere il confronto piuttosto che "profondo" perché i riferimenti non vengono seguiti - ad esempio, se l'oggetto osservato contiene un valore di proprietà che è un riferimento a un altro oggetto, quel riferimento non viene seguito per il confronto l'altro oggetto.


1
Ah, fantastico! C'è qualche motivo per cui questo non sembra essere tutto documentato (cioè, non penso che nessuno dei tutorial sul sito angolare abbia menzionato l'impostazione diretta di $ watches)? C'è qualcosa di negativo in questo che renderebbe la creazione di ng-changehook (potenzialmente multipli) sui controlli di input un'idea migliore?
Alec

12
Sì, sarebbe bello se il tutorial principale menzionasse $ watch da qualche parte. Ciò che è "cattivo" in questo approccio è che può richiedere molto tempo se il tuo modello è grande (ogni ciclo digest - ogni battitura in un campo di input - risulterà in questo modello che viene controllato in profondità, possibilmente più volte) . In tal caso, sarebbe meglio $ watch () es selettivo o ng-change selettivo.
Mark Rajcok

8

E se hai bisogno di modellare i tuoi elementi del modulo in base al suo stato (modificato / non modificato) dinamicamente o per verificare se alcuni valori sono effettivamente cambiati, puoi utilizzare il seguente modulo, sviluppato da me: https://github.com/betsol / angolare input-modificato

Aggiunge proprietà e metodi aggiuntivi al form e ai suoi elementi figlio. Con esso, puoi verificare se qualche elemento contiene nuovi dati o anche verificare se l'intero modulo ha nuovi dati non salvati.

Puoi impostare il seguente watch: $scope.$watch('myForm.modified', handler)e il tuo gestore verrà chiamato se alcuni elementi del modulo contengono effettivamente nuovi dati o se è tornato allo stato iniziale.

Inoltre, è possibile utilizzare la modifiedproprietà dei singoli elementi del modulo per ridurre effettivamente la quantità di dati inviati a un server tramite una chiamata AJAX. Non è necessario inviare dati invariati.

Come bonus, puoi ripristinare il tuo modulo allo stato iniziale tramite la chiamata al reset()metodo del modulo .

Puoi trovare la demo del modulo qui: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Saluti!


C'è un modo per verificarlo nel controller. per esempio se clicco sul pulsante x posso fare come un if (myform.modified) mostra popup di conferma?
Flash

Ovviamente, passa semplicemente FormController alla funzione del controller: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Slava Fomin II

grazie questo farà qualcosa solo se il form è stato modificato giusto?
Flash

Questo passerà FormControlleralla doSomething()funzione del tuo controller. Puoi fare tutto ciò che vuoi con esso all'interno di quella funzione, ad esempio controllare se il form è effettivamente modificato controllando la FormController.modifiedproprietà booleana.
Slava Fomin II

Grazie! Bella caratteristica
Flash
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.