[angularjs] How to deep watch an array in angularjs?

Setting the objectEquality parameter (third parameter) of the $watch function is definitely the correct way to watch ALL properties of the array.

$scope.$watch('columns', function(newVal) {
    alert('columns changed');
},true); // <- Right here

Piran answers this well enough and mentions $watchCollection as well.

More Detail

The reason I'm answering an already answered question is because I want to point out that wizardwerdna's answer is not a good one and should not be used.

The problem is that the digests do not happen immediately. They have to wait until the current block of code has completed before executing. Thus, watch the length of an array may actually miss some important changes that $watchCollection will catch.

Assume this configuration:

$scope.testArray = [
    {val:1},
    {val:2}
];

$scope.$watch('testArray.length', function(newLength, oldLength) {
    console.log('length changed: ', oldLength, ' -> ', newLength);
});

$scope.$watchCollection('testArray', function(newArray) {
    console.log('testArray changed');
});

At first glance, it may seem like these would fire at the same time, such as in this case:

function pushToArray() {
    $scope.testArray.push({val:3});
}
pushToArray();

// Console output
// length changed: 2 -> 3
// testArray changed

That works well enough, but consider this:

function spliceArray() {
    // Starting at index 1, remove 1 item, then push {val: 3}.
    $testArray.splice(1, 1, {val: 3});
}
spliceArray();

// Console output
// testArray changed

Notice that the resulting length was the same even though the array has a new element and lost an element, so as watch as the $watch is concerned, length hasn't changed. $watchCollection picked up on it, though.

function pushPopArray() {
    $testArray.push({val: 3});
    $testArray.pop();
}
pushPopArray();

// Console output
// testArray change

The same result happens with a push and pop in the same block.

Conclusion

To watch every property in the array, use a $watch on the array iteself with the third parameter (objectEquality) included and set to true. Yes, this is expensive but sometimes necessary.

To watch when object enter/exit the array, use a $watchCollection.

Do NOT use a $watch on the length property of the array. There is almost no good reason I can think of to do so.