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".

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

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.

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
}

Please tell more about your usecase. One of the solutions of tracking element persistance is using ngRepeat directive with custom directive that listening element's $destroy event:

<div ng-repeat="item in items" on-delete="doSomething(item)">

angular.module("app").directive("onDelete", function() {
    return {
        link: function (scope, element, attrs) {
            element.on("$destroy", function () {
                scope.$eval(attrs.onDelete);
            });
        }
    }
});

Perhaps the solution is to create the collection class ( like backbone does ) and you can hook into events pretty easily as well.

The solution I have done here isnt really comprehensive, but should give you a general guidance on how this could be done perhaps.

http://beta.plnkr.co/edit/dGJFDhf9p5KJqeUfcTys?p=preview