Angularjs - $scope.$destroy doesn't remove watchers
Asked Answered
D

1

0

I am trying to figure out how to create my own "one time binding", for Angularjs <= 1.2. I found this answer, describing how to create your own bindOnce directive. I do see that when using the following directive:

    app.directive('bindOnce', function() {
    return {
            scope: true,
            link: function( $scope ) {
                setTimeout(function() {
                    $scope.$destroy();
                }, 0);
            }
        }
    });

Data is binded once. But, I can see that the $$watchers is still on. Take a look at the following JSBin - running the commented watcher count code on the console will reveal that the watchers are still alive.

EDIT: for some reason, when using the same directive with angular 1.3, the watcher count dod changed to be 0!!!

Draghound answered 10/12, 2014 at 11:57 Comment(4)
Have you tried using $timeout instead of setTimeout?Privatdocent
Have you looked at github.com/Pasvaz/bindonce?Abeyta
@JonSnow: I did, it does not change anything. Regarding "github.com/Pasvaz/bindonce" - it does the work. I wanted to understand what happens behind the scenes.Draghound
@Abeyta you are correct, bindonce did the trick, although I was looking for a simpler solution. tnx!Draghound
L
-1

Use the cleanup function to remove watchers:

function cleanup(element) 
  { 
  element.off().removeData();

  var injector = currentSpec.$injector;

  element.$injector = null;

  // clean up jquery's fragment cache
  angular.forEach(angular.element.fragments, function(val, key) {
    delete angular.element.fragments[key];
  });

  angular.forEach(angular.callbacks, function(val, key) 
    {
    delete angular.callbacks[key];
    });

  angular.callbacks.counter = 0;
  }

Use a self-destructing service as a simple bind once:

function onetime()
  {
  /*...*/
  onetime = Function;
  }

angular.module('myApp').constant('bindonce', onetime);

angular.module('myApp').controller('foo', function($bindonce){
  this.$inject = '$bindonce';
  $scope.mybind = $bindonce();
} 

Use the migration guide for reference to find breaking changes:

References

Loreleilorelie answered 10/12, 2014 at 11:58 Comment(1)
Please note that my question specifically mentioned I am seeking for a solution using Angular 1.2.X. The {{::attr}} is for Angular 1.3+Draghound

© 2022 - 2024 — McMap. All rights reserved.