ng-change erhält neuen Wert und ursprünglichen Wert

118

Ich verwende ng-Optionen, um Werte aus einem Pulldown auszuwählen. Ich möchte den alten Wert mit dem neuen Wert vergleichen können. ng-change funktioniert gut, um den neuen Wert des Pulldowns zu ermitteln. Wie kann ich jedoch sowohl den neuen als auch den ursprünglichen Wert ermitteln?

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

Angenommen, ich wollte, dass der Controller protokolliert: "Ihr früherer Benutzername war BILL, Ihr aktueller Benutzername ist PHILLIPE."

Bailey Smith
quelle
1
Überprüfen Sie meine Antwort hier stackoverflow.com/questions/21909163/… könnte doppelt sein
bresleveloper
Ich bin mir nicht sicher, wie dies administrativ funktioniert, aber irgendwie sollten die Antworten aus dem Duplikat mit diesem zusammengeführt werden. bresleveloper ist eine nette Lösung (aus dem Duplikat), aber die TGH-Antwort sollte auch angezeigt werden. Die erste basiert auf Rahmenbedingungen, die sich in Zukunft ändern könnten, während die zweite rahmenunabhängig ist.
user1821052

Antworten:

279

Mit einem eckigen {{Ausdruck}} können Sie den alten Wert user oder user.id als Literalzeichenfolge zum Attribut ng-change hinzufügen:

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

In ngChange ist das erste Argument für updateValue der neue Benutzerwert. Das zweite Argument ist das Literal, das gebildet wurde, als das select-Tag zuletzt durch Angular mit dem alten Wert user.id aktualisiert wurde.

db-inf
quelle
6
Beachten Sie, dass der userAufruf der Methode in derjenige von ng-modelund nicht von ng-options ist (möglicherweise irreführend). Hoffentlich funktioniert diese elegante Lösung auch in zukünftigen Versionen von
Angular
15
Dies sollte als schädlich angesehen werden. Ich bin gerade auf einen schmutzigen Fehler gestoßen, der aufgetreten ist, als user.id ein Sonderzeichen enthält (wie 'oder /). Dies liegt daran, dass der Parser für Angular-Ausdrücke keinen Ausdruck wie updateValue mag (user,' blah / blah ').
Antoine Banctel-Chevrel
2
In der Funktion updateValue enthält $ scope.user.id bereits den neu ausgewählten Wert - es ist nicht erforderlich, einen Parameter für den neuen Wert an ihn zu übergeben
Majix
@ LINQ2Vodka, ich denke, es funktioniert nur ohne Anführungszeichen, wenn das user.idnumerisch ist ... es wird nicht funktionieren, wenn user.ides eine Zeichenfolge oder eine Guid ist
Tamas
1
schön :))))
Makatun
16

Auch können Sie verwenden

<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
quelle
1
Diese Antwort funktioniert sehr gut mit ng-repeat. Sie können stattdessen auch ng-click verwenden, wenn das Element, für das Sie dies verwenden, ng-change, aber nicht ng-focus unterstützt.
Meticoeus
1
ng-init = "oldValue = 0" & ng-focus = "oldValue = user.id" hat den Trick für mich gemacht.
Thatzprem
14

Sie können so etwas wie ng-change = someMethod ({{user.id}}) verwenden. Wenn Sie Ihren Wert in Seite {{Ausdruck}} belassen, wird der Ausdruck inline ausgewertet und der aktuelle Wert angezeigt (Wert vor dem Aufruf der ng-change-Methode).

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

Behalten Sie einfach eine currentValue-Variable in Ihrem Controller, die Sie bei jeder Änderung aktualisieren. Sie können dies dann jedes Mal mit dem neuen Wert vergleichen, bevor Sie ihn aktualisieren. '

Die Idee, eine Uhr zu verwenden, ist ebenfalls gut, aber ich denke, eine einfache Variable ist die einfachste und logischste Lösung.

TGH
quelle
Uhr ist wenig teure Operation, ich mochte die Antwort von db-inf .. es ist einfach funktionierende Lösung
Pramod Sharma
4
Beste Antwort. Wenn Sie sich in einer ng-Wiederholung befinden, erstellen Sie mit ng-init eine Variable im Unterbereich.
Romain F.
1
IMHO ist dies die beste Alternative. Da das Abrufen alter Werte nicht standardmäßig von ngChange bereitgestellt wird, können Lösungen wie die von @ db-inf in zukünftigen Versionen implodieren. Außerdem klingt dies wie die Verantwortung eines Controllers, und es scheint seltsam, sie an die Ansichtsebene zu delegieren.
Felipe Leão
9

Sie können eine Zielfernrohruhr verwenden:

$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

Tommybananas
quelle
6
Ich bin auf einen Artikel gestoßen, der besagt, dass die Uhr im Vergleich zu ng-change viel schmutziger / ineffizienter ist. benlesh.com/2013/10/title.html
Menios
5
Nach meiner Erfahrung möchten Sie fast nie eine Uhr benutzen
Nardnob
2
Wenn Programmieren eine subjektive Kunst wäre, könnten Sie dort etwas haben. Leider - es gibt viele Gründe, warum Sie möglicherweise Ng-Charge oder andere richtlinienbasierte Ansätze vermeiden möchten, die nichts damit zu tun haben, Dinge auf "eckige" Weise zu tun.
Tommybananas
2

Sie könnten stattdessen eine Uhr verwenden, da diese den alten und den neuen Wert hat, aber dann fügen Sie dem Digest-Zyklus etwas hinzu.

Ich würde nur eine zweite Variable im Controller behalten und diese einstellen.

user12121234
quelle
Dies ist ein ziemlich triviales Beispiel. Ich würde die Lesbarkeit der Sorge um einen einzelnen Beobachter in diesem Fall übernehmen. Es ist immer noch eine gute Sache, müde zu sein, nehme ich an.
Tommybananas
1
Watch und ng-change haben tatsächlich unterschiedliche Verhaltensweisen: ng-change erkennt nur Benutzerereignisse, während $watches jedes Mal ausgelöst wird, wenn sich die Variable ändert. Beobachter erhöhen die Komplexität und neigen dazu, Aktualisierungszyklen zu erstellen, wenn Code ihre Werte ändert.
Rhys van der Waerden
Ich stimme @Rhys van der Waerden zu ... dieser Artikel besagt, dass $ watch ein bisschen gefährlich ist: benlesh.com/2013/10/title.html
Menios