0

For example, I have a custom directive that I use like this:

<my-directive ng-if="showThis"></my-directive>

I need to perform some DOM-manipulations and attach/remove event handlers when showThis that defined in rootScope turns to true or false. It might happens many times during workflow. That's why I have some questions:

  1. Can I handle the change of ng-if?

  2. Where should I do this: inside link function or controller function of myDirective?

  3. Does I really need to kill and reattach event listeners each time to avoid memory leaks? Or AngularJS will do it for me?

  4. Will link and controller functions be called each time, when ng-if turns to true?

deceze
  • 510,633
  • 85
  • 743
  • 889
splash27
  • 2,057
  • 6
  • 26
  • 49
  • 3
    You can use watch on showThis. – binariedMe Oct 05 '16 at 07:17
  • When `showThis` turns `false`, the entire `my-directive` element will be removed from the DOM. I'm not entirely sure off the top of my head how `my-directive` would catch wind of this, but presumably the associated scope would be destroyed, which you can watch for. – deceze Oct 05 '16 at 07:19
  • Have you actually tried anything yet? Because It doesn't look like it – Alon Eitan Oct 05 '16 at 07:20

2 Answers2

4

Can I handle the change of ng-if?
When the expression inside ng-if evaluates to false, angular removes your directive from the DOM and $scope.$destroy event is fired.

Where should I do this: inside link function or controller function of myDirective?
Since your directive is removed from the DOM, neither controller no link function is of any help to you.

Do I really need to kill and reattach event listeners each time to avoid memory leaks? Or AngularJS will do it for me?
All $watch listeners attached to the destroyed scope will be removed by Angular. However, if you attached watchers to other scopes, like $rootScope, you have to remove them manually. All DOM event listeners attached to the DOM inside your directive are removed by a browser when DOM elements are destroyed. If you have any event listeners attached to the DOM that is not destroyed (outside your directive), you will have to remove them manually.

Will link and controller functions be called each time, when ng-if turns to true?
Yes

This answer provides more information about what to do when the directive is destroyed.

Community
  • 1
  • 1
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
2

There's one question you need to consider before deciding on a solution: do you want the ng-if handler to run in the container controller, or within the my-directive link function.

If the handler is scoped to the container controller, you can just $scope.$watch('showThis', handler), run during instantiation of the container controller.

However if it's scoped to the directive, you'll probably looking for $scope.$on('$destroy', handler).

In answer to your questions:

  1. Inside the link function, using the $scope which is provided in the function signature.

  2. Angular will clean up event listeners that it knows about - anything attached using ng-click/ng-change/ng-whatever or $watches called on $scope. However if you're binding events by native javascript: yes, you should clean up. There is one major exception to that rule though - if you're binding to a DOM element that gets destroyed when the directive is destroyed, the JS engine will of course free up that memory for you automatically.

  3. As @Maximus said above, the functions will be run every time the ng-if value is true since the DOM element is completely removed/added.

Simon Robb
  • 1,668
  • 1
  • 14
  • 25