How to stop $observe in AngularJS

angularjs, angularjs-directive, javascript

Solution

AngularJS 1.3 and above

In Angular 1.3 and above, $observe returns the deregister function, so deregistering $observe works exactly as for $watch:

var stopObserving = attrs.$observe(...);
stopObserving();

AngularJS 1.2 and below

In AngularJs 1.2 there is no way to deregister an observer, and, as you rightly noted, $observe returns the callback function.

There is however currently a PR open to change $observe to also return a deregistration function similar to $watch and $on, unfortunately this is only triaged for the 1.3 release because of the breaking change. The PR is over here: https://github.com/angular/angular.js/pull/5609

Good news is it takes a full 3 new lines of code to implement the change, as per the PR, so if you can't wait until the 1.3 release you can easily implement this yourself.

Problem

I had recently some issues with jQuery plugins in directives in Angular not being properly cleaned and hence, creating Memory Leaks. So, today, while I was working on tests to ensure that won't happen, I realised that there is no way to stop observing. ``` var stopObserving = attrs.$observe('myProperty', function(newValue) { updateElement(newValue); }); ``` Since I thought it worked the same way it does on `$watch` but clearly it doesn't. According to the docs, `$observe` will return the callback function, that's it, the second argument. I have this test: ``` describe('destroy',function(){ beforeEach(function(){ $scope.$destroy(); }); it('should have emptied the DOM node', function(){ expect(element.text()).toBe(''); }); it('shouldn\'t have any more watchers', function(){ dump(element.data().$scope.$$watchers); expect(element.data().$scope.$$watchers.length).toBe(0); }); }); ``` And it fails, cause there is one watcher. I've checked and the `$destroy` is being called and hence, the cleaning is done. However, how can I get rid of that watcher? The code, in case you're curious is here: https://github.com/firstandthird/angular-popbox

Original source