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.