ng-change uzyskaj nową wartość i oryginalną wartość

118

Używam opcji ng-options do wybierania wartości z menu rozwijanego. Chciałbym móc porównać starą wartość z nową wartością. ng-change działa dobrze przy przechwytywaniu nowej wartości rozwijania, ale jak mogę uzyskać zarówno nową, jak i oryginalną wartość?

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

Na przykład, powiedzmy, że chcę, aby kontroler zarejestrował: „Twoja poprzednia nazwa.użytkownika to BILL, a Twoja obecna nazwa użytkownika to PHILLIPE”.

Bailey Smith
źródło
1
sprawdź moją odpowiedź tutaj stackoverflow.com/questions/21909163/ ... może być zduplikowany
bresleveloper
Nie jestem pewien, jak to działa administracyjnie, ale jakoś odpowiedzi z duplikatu powinny zostać połączone z tym. bresleveloper to fajne rozwiązanie (z duplikatu), ale odpowiedź TGH powinna być również pokazana. Pierwszy opiera się na działaniu frameworka, który może się zmienić w przyszłości, a drugi jest agnostykiem frameworka.
user1821052

Odpowiedzi:

279

Za pomocą kątowego {{wyrażenie}} możesz dodać starą wartość user lub user.id do atrybutu ng-change jako ciąg literału:

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

W ngChange pierwszym argumentem updateValue będzie nowa wartość użytkownika, drugim argumentem będzie literał, który został utworzony, gdy tag select był ostatnio aktualizowany przez angular, ze starą wartością user.id.

db-inf
źródło
6
Zauważ, że userwywołanie metody in jest tym z ng-model, a nie z ng-options (może być mylące). Miejmy nadzieję, że to eleganckie rozwiązanie zadziała również w przyszłych wersjach
angulara
15
Należy to uznać za szkodliwe. Właśnie natknąłem się na brudny błąd występujący, gdy user.id zawiera znak specjalny (taki jak 'lub /), ponieważ parser wyrażeń Angular nie lubi wyrażeń takich jak updateValue (użytkownik,' bla / bla ').
Antoine Banctel-Chevrel
2
W funkcji updateValue $ scope.user.id zawiera już nowo wybraną wartość - nie ma potrzeby przekazywania do niej parametru dla nowej wartości
Majix 31.07
@ LINQ2Vodka, myślę, że działa tylko bez cudzysłowów, jeśli user.idjest numeryczny ... nie zadziała, jeśli user.idjest ciągiem lub guid
Tamas
1
piękny :))))
Makatun
16

Możesz również użyć

<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>
Umut Catal
źródło
1
Ta odpowiedź działa naprawdę dobrze w przypadku powtórzenia ng. Możesz także użyć ng-click, jeśli element, którego używasz, obsługuje zmianę ng-change, ale nie ng-focus.
meticoeus
1
ng-init = "oldValue = 0" & ng-focus = "oldValue = user.id" załatwiło sprawę.
thatzprem
14

Możesz użyć czegoś takiego jak ng-change = someMethod ({{user.id}}). Trzymając swoją wartość w side {{expression}}, obliczy ona wyrażenie w linii i poda aktualną wartość (wartość przed wywołaniem metody ng-change).

<select ng-model="selectedValue" ng-change="change(selectedValue, '{{selectedValue}}')">
Vivek Panday
źródło
13

Po prostu zachowaj zmienną currentValue w kontrolerze, którą aktualizujesz przy każdej zmianie. Następnie możesz porównać to z nową wartością za każdym razem, zanim ją zaktualizujesz.

Pomysł wykorzystania zegarka też jest dobry, ale myślę, że prosta zmienna jest najprostszym i najbardziej logicznym rozwiązaniem.

TGH
źródło
Zegarek jest mało kosztowną operacją, podobała mi się odpowiedź db-inf .. to proste rozwiązanie robocze
Pramod Sharma
4
Najlepsza odpowiedź. Jeśli jesteś wewnątrz powtórzenia ng, utwórz zmienną w podzakresie za pomocą ng-init.
Romain F.
1
IMHO to najlepsza alternatywa. Ponieważ ngChange nie zapewnia natychmiastowego pobierania starych wartości, rozwiązania takie jak @ db-inf mogą implodować w przyszłych wersjach. Poza tym brzmi to jak odpowiedzialność kontrolera, wydaje się dziwne delegowanie go do warstwy widoku.
Felipe Leão
9

Możesz użyć lunety:

$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

tommybanany
źródło
6
Natknąłem się na artykuł, w którym stwierdzono, że zegarek jest znacznie bardziej brudny / nieefektywny w porównaniu do zmiany ng. benlesh.com/2013/10/title.html
Menios
5
Z mojego doświadczenia
wynika,
2
Gdyby programowanie było sztuką subiektywną, mógłbyś coś tam mieć. Niestety - istnieje wiele powodów, dla których możesz chcieć uniknąć ng-charge lub innych podejść opartych na dyrektywach, niezwiązanych z robieniem rzeczy w sposób „kątowy”.
tommybananas
2

Możesz zamiast tego użyć zegarka, ponieważ ma on starą i nową wartość, ale potem dodajesz do cyklu podsumowania.

Po prostu zatrzymałbym drugą zmienną w kontrolerze i ustawiłbym ją.

user12121234
źródło
To dość trywialny przykład, w tym przypadku wolałbym czytać niż martwić się o jednego obserwatora. Myślę, że nadal dobrze jest być znudzonym.
tommybananas
1
Watch i ng-change w rzeczywistości mają różne zachowania: ng-change wykrywa tylko zdarzenia użytkownika, podczas gdy $watchbędzie uruchamiany za każdym razem, gdy zmienna ulegnie zmianie. Obserwatorzy zwiększają złożoność i są podatni na tworzenie cykli aktualizacji, gdy kod zmienia ich wartości.
Rhys van der Waerden
Zgadzam się z @Rhys van der Waerden ... ten artykuł stwierdza, że ​​$ watch jest nieco niebezpieczny: benlesh.com/2013/10/title.html
Menios