AngularJS : Clear $watch

AngularJS : Clear $watch

I have a watch function in my AngularJS application.
$scope.$watch(‘quartzCrystal’, function () {

}

However, after some condition (in my example, changing the page at my single-page application) I want to stop that watch (as like clearing timeout).
How can I do that?

Solutions/Answers:

Solution 1:

$watch returns a deregistration function. Calling it would deregister the $watcher.

var listener = $scope.$watch("quartz", function () {});
// ...
listener(); // Would clear the watch

Solution 2:

scope.$watch returns a function that you can call and that will unregister the watch.

Something like:

var unbindWatch = $scope.$watch("myvariable", function() {
    //...
});

setTimeout(function() {
    unbindWatch();
}, 1000);

Solution 3:

You can also clear the watch inside the callback if you want to clear it right after something happens. That way your $watch will stay active until used.

Like so…

var clearWatch = $scope.$watch('quartzCrystal', function( crystal ){
  if( isQuartz( crystal )){
    // do something special and then stop watching!
    clearWatch();
  }else{
    // maybe do something special but keep watching!
  } 
}

Solution 4:

Some time your $watch is calling dynamically and it will create its instances so you have to call deregistration function before your $watch function

if(myWatchFun)
  myWatchFun(); // it will destroy your previous $watch if any exist
myWatchFun = $scope.$watch("abc", function () {});

Solution 5:

If you have too much watchers and you need to clear all of them, you can push them into an array and destroy every $watch in a loop.

var watchers = [];
watchers.push( $scope.$watch('watch-xxx', function(newVal){
   //do something
}));    

for(var i = 0; i < watchers.length; ++i){
    if(typeof watchers[i] === 'function'){
        watchers[i]();
    }
}

watchers = [];

Solution 6:

Ideally, every custom watch should be removed when you leave the scope.

It helps in better memory management and better app performance.

// call to $watch will return a de-register function
var listener = $scope.$watch(someVariableToWatch, function(....));

$scope.$on('$destroy', function() {
    listener(); // call the de-register function on scope destroy
});