Подтвердить что ты не робот

AngularJS: $часы не запускаются для изменения массива объектов

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

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "OT", "NY"]
    },
    {
        "columnName": "weather",
        "values": ["humid", "sunny"]
    }
];

Таким образом, объекты в массиве содержат ключи "columnName" и "values". "columnName" означает столбец для фильтра, а "значения" - значения фильтра. В основном, вышеупомянутый массив приведет к строкам в таблице, для которых в столбце города содержатся значения "LA", "OT" или "NY" в качестве значений, а погодный столбец содержит "влажный" или "солнечный" в качестве значений. Другие строки, которые не содержат этих значений, не отображаются.

Чтобы лучше понять этот объект, если пользователь хочет видеть только те строки, у которых есть "LA" или "NY" в столбце "city", результирующий массив будет выглядеть так:

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "NY"]
    },
    {
        "columnName": "weather",
        "values": []
    }
];

Пользователь устанавливает или удаляет эти фильтры. Всякий раз, когда это происходит, этот массив обновляется. Это обновление происходит правильно, и я проверил его - здесь нет проблем.

Проблема заключается в $watch(). У меня есть следующий код:

$scope.$watch('activeFilterAttributes', function() {
    //Code that should update the rows displayed in the table based on the filter
}}

В то время как $scope.activeFilterAttributes обновляется должным образом, и когда пользователь обновил фильтр в пользовательском интерфейсе, $watch не запускается, когда он обновляется. Он запускается в первый раз, когда приложение загружается, но будущие обновления не влияют на это.

Я создал скрипку, чтобы продемонстрировать это: http://jsfiddle.net/nCHQV/

В скрипке $scope.info представляет собой строки таблицы, так сказать.
$scope.data представляет фильтр.
Нажатие на кнопку эквивалентно обновлению фильтра (в случае скрипта - данных) и, таким образом, обновлению строк, отображаемых в таблице (в случае скрипта - информация). Но, как видно, информация не обновляется при нажатии кнопки.

Не следует ли срабатывать $scope.$watch при изменении массива объектов?

4b9b3361

Ответ 1

Метод $watch принимает необязательный третий параметр с именем objectEquality, который проверяет, что оба объекта равны, а не просто используют одну и ту же ссылку. Это не поведение по умолчанию, потому что это более дорогая операция, чем контрольная проверка. Ваши часы не запускаются, потому что они все еще относятся к одному и тому же объекту.

Подробнее см. docs.

$scope.$watch('activeFilterAttributes', function() {
  // ...
}, true); // <-- objectEquality

Добавьте этот параметр и все хорошо.

Ответ 2

Принятый ответ немного устарел, как и в случае с AngularJS 1.1.4, функция $WatchCollection была добавлена ​​для использования с массивами и другими коллекциями, что намного дешевле, чем $Watch с установленным флагом глубокого равенства к true.

Таким образом, эта новая функция теперь предпочтительнее в большинстве ситуаций.

См. в этой статье для более подробных различий между $Watch функциями