ng-change ottiene nuovo valore e valore originale


118

Sto usando ng-options per selezionare i valori da un menu a discesa. Mi piacerebbe poter confrontare il vecchio valore con il nuovo valore. ng-change funziona bene per acquisire il nuovo valore del pull down, ma come posso ottenere sia il nuovo valore che il valore originale?

<select ng-change="updateValue(user)" ng-model="user.id" ng-options="user.id as user.name for user in users"></select> 

Ad esempio, diciamo che volevo che il controller registrasse "Il tuo nome utente precedente era BILL, il nome utente corrente è PHILLIPE."


1
controlla la mia risposta qui stackoverflow.com/questions/21909163/… potrebbe essere duplicato
— bresleveloper

non sono sicuro di come funzioni dal punto di vista amministrativo, ma in qualche modo le risposte del duplicato dovrebbero essere unite a questo. bresleveloper è una bella soluzione (dal duplicato) ma dovrebbe essere mostrata anche la risposta TGH. Il primo si basa sul funzionamento del framework, che potrebbe cambiare in futuro, mentre il secondo è agnostico del framework.
— user1821052

Risposte:


279

Con una {{espressione}} angolare puoi aggiungere il vecchio valore user o user.id all'attributo ng-change come stringa letterale:

<select ng-change="updateValue(user, '{{user.id}}')" 
        ng-model="user.id" ng-options="user.id as user.name for user in users">
</select>

Su ngChange, il primo argomento di updateValue sarà il nuovo valore utente, il secondo argomento sarà il letterale formato quando il tag di selezione è stato aggiornato l'ultima volta da angular, con il vecchio valore user.id.


6
Notare che la userchiamata al metodo in è quella da ng-modele non da ng-options (potrebbe essere fuorviante). Speriamo che questa elegante soluzione funzioni anche nelle versioni future di
— angular

15
Questo dovrebbe essere considerato dannoso. Mi sono appena imbattuto in un bug sporco che si verifica quando user.id contiene un carattere speciale (come 'o /), perché al parser di espressioni angolari non piacciono espressioni come updateValue (user,' blah / blah ').
— Antoine Banctel-Chevrel

2
Nella funzione updateValue, $ scope.user.id contiene già il valore appena selezionato - non è necessario passare un parametro per il nuovo valore ad esso
— Majix

@ LINQ2Vodka, penso che funzioni solo senza virgolette se user.idè numerico ... non funzionerà se user.idè una stringa o un guid
— Tamas

1
bellissimo :))))
— Makatun

16

Inoltre puoi usare

<select ng-change="updateValue(user, oldValue)"     
       ng-init="oldValue=0"
       ng-focus="oldValue=user.id"
       ng-model="user.id" ng-options="user.id as user.name for user in users">
</select>

1
Questa risposta funziona davvero bene con ng-repeat. Puoi anche usare ng-click invece se l'elemento su cui stai usando questo supporta ng-change ma non ng-focus.
— meticoeus

1
ng-init = "oldValue = 0" & ng-focus = "oldValue = user.id" ha fatto il trucco per me.
— thatzprem

14

Puoi usare qualcosa come ng-change = someMethod ({{user.id}}). Mantenendo il tuo valore nel lato {{espressione}}, valuterà l'espressione in linea e ti darà il valore corrente (valore prima che venga chiamato il metodo ng-change).

<select ng-model="selectedValue" ng-change="change(selectedValue, '{{selectedValue}}')">

13

Mantieni una variabile currentValue nel tuo controller che aggiorni ad ogni modifica. Puoi quindi confrontarlo con il nuovo valore ogni volta prima di aggiornarlo. "

Anche l'idea di utilizzare un orologio è buona, ma penso che una semplice variabile sia la soluzione più semplice e logica.


L'orologio è un'operazione poco costosa, mi è piaciuta la risposta di db-inf .. è una semplice soluzione funzionante
— Pramod Sharma

4
Migliore risposta. Se ti trovi all'interno di un ng-repeat, crea una variabile nel sotto-ambito usando ng-init.
— Romain F.

1
IMHO questa è la migliore alternativa. Poiché il recupero dei vecchi valori non è fornito da ngChange out-of-the-box, soluzioni come quella da @ db-inf potrebbero implodere nelle versioni future. Inoltre, questo suona come la responsabilità di un controller, sembra strano delegarlo al livello di visualizzazione.
— Felipe Leão

9

Puoi usare uno scope watch:

$scope.$watch('user', function(newValue, oldValue) {
  // access new and old value here
  console.log("Your former user.name was "+oldValue.name+", you're current user name is "+newValue.name+".");
});

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch


6
Mi sono imbattuto in un articolo che afferma che l'orologio è molto più sporco / inefficiente rispetto a ng-change. benlesh.com/2013/10/title.html
— Menios

5
Nella mia esperienza non si vuole quasi mai usare un orologio
— nardnob

2
Se la programmazione fosse un'arte soggettiva potresti avere qualcosa lì. Ahimè, ci sono molte ragioni per cui potresti voler evitare la carica di energia o altri approcci basati sulla direttiva, non correlati al fare le cose in modo "angolare".
— tommybananas

2

Potresti invece usare un orologio, perché ha il valore vecchio e nuovo, ma poi stai aggiungendo al ciclo digest.

Tengo solo una seconda variabile nel controller e la imposto.


Questo è un esempio piuttosto banale, in questo caso considererei la leggibilità piuttosto che preoccuparmi di un singolo osservatore. Ancora una buona cosa di cui essere stanco suppongo.
— tommybananas

1
Watch e ng-change hanno effettivamente comportamenti diversi: ng-change rileva solo gli eventi dell'utente, mentre $watchsi attiva ogni volta che la variabile cambia. Gli osservatori aumentano la complessità e sono inclini a creare cicli di aggiornamento quando il codice modifica i propri valori.
— Rhys van der Waerden

Sono d'accordo con @Rhys van der Waerden ... questo articolo afferma che $ watch è un po 'pericoloso: benlesh.com/2013/10/title.html
— Menios
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.