Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to watch an array for changes in AngularJS

I basically want the equivalent to binding to 'add' and 'remove' events in Backbone's Collections. I see basically no way of doing this in AngularJS, and the current workaround we've settled for is $watch()ing the array's length and manually diffing/recalculating the whole thing. Is this really what the cool kids do?

Edit: Specifically, watching the array's length means I don't easily know which element has been changed, I need to manually "diff".

like image 964
abyx Avatar asked Mar 28 '13 12:03

abyx


3 Answers

I think using $watch is a good solution, but $watchCollection can be better for you. $watchCollection doesn't perform deep comparison and just watchs for array modification like insert, delete or sort (not item update).

For exemple, if you want to keep an attribut order synchronize with the array order :

$scope.sortableItems = [
    {order: 1, text: 'foo'},
    {order: 2, text: 'bar'},
    {order: 3, text: 'baz'}
];

$scope.$watchCollection('sortableItems', function(newCol, oldCol, scope) {
    for (var index in newCol) {
        var item = newCol[index];
        item.order = parseInt(index) + 1;
    }
});

But for your problem, I do not know if there is a better solution than manually browse the array to identify the change.

like image 197
Noémi Salaün Avatar answered Sep 28 '22 09:09

Noémi Salaün


The way to watch an array in Angular is $watch(array, function(){} ,true)

like image 36
Jason Als Avatar answered Sep 28 '22 08:09

Jason Als


I would create child scopes and watch them individually. here is an example:

$scope.myCollection = [];
var addChild = function()
{
  var Child = $scope.$new();
  Child.name = 'Your Name here';

  Child.$watch('name', function(newValue) {
     // .... do something when the attribute 'name' is changed ...
  });

  Child.$on('$destroy', function() {
    //... do something when this child gets destroyed 
  });


  $scope.myCollection.push(Child); // add the child to collection array

};

// Pass the item to this method as parameter, 
// do it within an ngRepeat of the collection in your views 
$scope.deleteButtonClicked = function(item)
{
  var index = $scope.myCollection.indexOf(item); //gets the item index
  delete $scope.myCollection[index]; // removes the item on the array
  item.$destroy(); // destroys the original items
}
like image 3
Raftalks Avatar answered Sep 28 '22 09:09

Raftalks