2015-09-24 2 views
0

Я хотел бы отслеживать изменения элементов в массиве. см. образец here:

angular.module('watchApp', []).controller('watchCtrl', function($scope) { 
$scope.items = [ 
    {value: 1}, 
    {value: 2}, 
    {value: 3} 
]; 

$scope.newItems = []; 
$scope.deleteItems = []; 
$scope.modifiedItems = []; 
$scope.$watchCollection('items', function(newVal, oldVal) { 
    console.log(newVal); 
    console.log(oldVal); 
    for(var i=0; i<newVal.length; i++) { 
     if (oldVal.indexOf(newVal[i])<0) { 
      $scope.newItems.push(newVal[i]); 
     } 
    } 
    for(var i=0; i<oldVal.length; i++) { 
     if (newVal.indexOf(oldVal[i])<0) { 
      $scope.deleteItems.push(oldVal[i]); 
     } 
    } 
}); 
$scope.addOne = function() { 
    $scope.items.push({value:$scope.items.length+1}); 
}; 
$scope.remove = function (it) { 
    $scope.items.splice($scope.items.indexOf(it), 1); 
}; 

});

Теперь я могу отслеживать новые добавленные и удаленные элементы с последней версией (1.5.0) угловой. Однако я не знаю, как получить измененные элементы в массиве. Просто используйте $watch('items', function..., true) не работает. который сделает все элементы как новые, а все старые элементы удалены, в том числе без изменений.

+0

'$ watch' и' $ watchCollection' просто говорят вам, что содержимое массива изменилось, вы несете ответственность за поиск разницы между старой и новой версией массива самостоятельно. – muenchdo

+0

Да, это то, о чем я думал. Кажется, что в угловом, если вы хотите отслеживать, что было изменено, а не просто запускать уведомление, это было бы довольно сложно и неэффективно. – cairabbit

+0

Нет, было бы неэффективно, если бы Angular всегда следил за тем, что было изменено, поскольку это сложнее вычислить и часто не требуется даже времени. – muenchdo

ответ

0

Внутри вашей функции $watchCollection вам необходимо рассчитать разницу между двумя версиями вашего массива. Я рекомендую использовать для этого lodash. Для проверки того, был ли элемент удален или добавлен, я сравниваю длины newValue и oldValue.

$scope.$watchCollection('items', function (newValue, oldValue) { 
    if (newValue.length > oldValue.length) { 
     console.log(_.difference(newValue, oldValue)); 
    } else { 
     console.log(_.difference(oldValue, newValue)); 
    } 
}); 

Проверьте это JSFiddle для простой демонстрации.

Если вы не хотите использовать lodash, вам нужно будет сравнить два массива вручную.

+0

Это просто пример, я знаю, что другие библиотеки могут проверять разницу между объектами и массивом. Я просто хочу знать, что является правильным способом в anguarjs. Другими словами, можно ли использовать watch или watchCollection, чтобы определить, что именно изменилось, а не просто запустить событие изменения. Иногда нам приходится обрабатывать особые случаи только тогда, когда указанный элемент в массиве изменился или указанное свойство элемента изменилось. В knockoutjs вы можете подписаться на событие с указанным свойством или другим наблюдаемым объектом. Как это происходит в angularjs. – cairabbit

+0

Как я уже упоминал в своем комментарии к вашему вопросу, '$ watch' и' $ watchCollection' не сообщают вам о конкретных элементах, которые изменились. Они дают вам старую и новую версию, чтобы вы могли сравнивать себя (это было бы плохо для производительности, если бы Angular всегда делал это, даже если вам это не нужно). То, как я показывал, является правильным способом в Угловом. – muenchdo

+0

Спасибо muenchdo. – cairabbit

Смежные вопросы