Watch variable and change it

Vivendi picture Vivendi · Aug 15, 2014 · Viewed 60.1k times · Source

In AngularJS I have a directive that watches a scope variable. When the variable contains certain data then I need to alter that variable a bit. The problem is that when I change the variable that my $watch is triggered again. So I end up in a continuous loop.

scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    scope.someVar = [Do something with someVar];
});

This keeps triggering $watch again, which makes sense. But I do need a way to change the watched variable. Is there a way to do this?

Answer

pixelbits picture pixelbits · Aug 15, 2014

When a variable is watched for changes using $scope.$watch, angular checks if the reference has changed. If it has, then the $watch handler is executed to update the view.

If you plan on changing the scope variable within the $watch handler, it will trigger an infinite $digest loop because the scope variable reference changes every time that it is called.

The trick to getting around the infinite digest issue is to preserve the reference inside your $watch handler using angular.copy (docs):

scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    var someVar = [Do something with someVar];

    // angular copy will preserve the reference of $scope.someVar
    // so it will not trigger another digest 
    angular.copy(someVar, $scope.someVar);

});

Note: This trick only works for object references. It will not work with primitives.

In general, its not a good idea to update a $watched variable within its own $watch listener. However, sometimes it may be unavoidable.