ng-change получить новое значение и исходное значение

118

Я использую ng-options для выбора значений из раскрывающегося списка. Я бы хотел сравнить старое значение с новым. ng-change хорошо подходит для получения нового значения раскрывающегося списка, но как я могу получить и новое значение, и исходное значение?

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

Например, скажем, я хотел, чтобы контроллер регистрировал: «Ваше прежнее имя пользователя было BILL, ваше текущее имя пользователя - PHILLIPE».

Бейли Смит
источник
1
проверьте мой ответ здесь stackoverflow.com/questions/21909163/… может быть дубликатом
bresleveloper
не уверен, как это работает административно, но каким-то образом ответы дубликата должны быть объединены с этим. bresleveloper - хорошее решение (из дубликата), но также должен быть показан ответ TGH. Первый основан на работе фреймворка, который может измениться в будущем, а второй не зависит от фреймворка.
user1821052 04

Ответы:

279

С помощью angular {{выражение}} вы можете добавить старое значение user или user.id к атрибуту ng-change в виде буквальной строки:

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

В ngChange 1-м аргументом updateValue будет новое значение пользователя, 2-м аргументом будет литерал, который был сформирован, когда тег select был в последний раз обновлен angular со старым значением user.id.

дб-инф
источник
6
Обратите внимание, что userвызов метода in - это вызов из ng-model, а не из ng-options (может вводить в заблуждение). Надеюсь, это элегантное решение будет работать и в будущих версиях angular :)
icl7126, 04
15
Это следует считать вредным. Я только что столкнулся с грязной ошибкой, возникающей, когда user.id содержит специальный символ (например, 'или /). Это связано с тем, что синтаксическому анализатору угловых выражений не нравятся такие выражения, как updateValue (user,' blah / blah ').
Антуан Бантель-Шеврель,
2
В функции updateValue $ scope.user.id уже содержит новое выбранное значение - нет необходимости передавать ему параметр для нового значения
Majix
@ LINQ2Vodka, я думаю, он работает без кавычек, только если user.idчисловой ... он не будет работать, если user.idэто строка или руководство
Тамас
1
красиво :))))
Макатун
16

Также вы можете использовать

<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
Этот ответ действительно хорошо работает с ng-repeat. Вместо этого вы также можете использовать ng-click, если элемент, в котором вы его используете, поддерживает ng-change, но не ng-focus.
meticoeus
1
ng-init = "oldValue = 0" & ng-focus = "oldValue = user.id" помогло мне.
thatzprem
14

Вы можете использовать что-то вроде ng-change = someMethod ({{user.id}}). Сохраняя ваше значение в стороне {{выражение}}, он будет оценивать выражение в строке и давать вам текущее значение (значение до вызова метода ng-change).

<select ng-model="selectedValue" ng-change="change(selectedValue, '{{selectedValue}}')">
Вивек Пандай
источник
13

Просто сохраните в контроллере переменную currentValue, которую вы обновляете при каждом изменении. Затем вы можете сравнивать это с новым значением каждый раз, прежде чем обновлять его ».

Идея использования часов тоже хороша, но я думаю, что простая переменная - это самое простое и логичное решение.

TGH
источник
Часы - это немного дорогая операция, мне понравился ответ db-inf .. это простое рабочее решение
Прамод Шарма
4
Лучший ответ. Если вы находитесь внутри ng-repeat, создайте переменную в подпространстве с помощью ng-init.
Ромен Ф.
1
ИМХО это лучшая альтернатива. Поскольку извлечение старых значений в ngChange не предусмотрено, решения, подобные решению от @ db-inf, могут не сработать в будущих версиях. Кроме того, это звучит как ответственность контроллера, кажется странным делегировать ее слою представления.
Фелипе Леан
9

Вы можете использовать прицел часы:

$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
источник
6
Я наткнулся на статью, в которой говорится, что часы намного грязнее / неэффективнее по сравнению с ng-change. benlesh.com/2013/10/title.html
Menios
5
По моему опыту, вы почти никогда не захотите использовать часы
нардноб
2
Если бы программирование было субъективным искусством, у вас могло бы быть что-то там. Увы, есть много причин, по которым вы можете захотеть избежать ng-charge или других подходов, основанных на директивах, не связанных с "угловым" способом.
tommybananas
2

Вместо этого вы можете использовать часы, потому что они имеют старое и новое значение, но затем вы добавляете их в цикл дайджеста.

Я бы просто сохранил вторую переменную в контроллере и установил ее.

user12121234
источник
Это довольно тривиальный пример, я бы предпочел удобочитаемость беспокоиться об одном наблюдателе в этом случае. Полагаю, это все еще неплохо, чтобы от этого устать.
tommybananas
1
Watch и ng-change на самом деле имеют разное поведение: ng-change обнаруживает только пользовательские события, тогда как $watchсрабатывает каждый раз при изменении переменной. Наблюдатели увеличивают сложность и склонны создавать циклы обновления, когда код меняет свои значения.
Рис ван дер Варден,
Я согласен с @Rhys van der Waerden ... в этой статье говорится, что $ watch немного опасен: benlesh.com/2013/10/title.html
Menios