简体   繁体   中英

Using $scope.$destroy() after removing directive from dom

I have a directive which I toggle with ng-if condition. The directive uses jqlite functions to add elements ( eg some animation ) on DOM.

But even when the directive is not present in DOM, the jqlite functions that add animation are triggered.

I think that removing the directive using ng-if is not enough, but its scope also needs to be removed.

somepage.html - edited

<directivename class="classname1" ng-if="condition">
</directivename>

directive.js

return{
controller:function($scope,$element,$rootScope){
/*adding and removing elemnts to dom */
}
}

How exactly should I use $scope.$destroy() ?

When I see the values for the $element variable, It has following

$$hashKey: "object:336"
accessKey: ""
attributes: NamedNodeMap
baseURI: ""
childElementCount: 1
childNodes: NodeList[3]
children: HTMLCollection[1]
classList: DOMTokenList[3]
0: "classname1"
1: "ng-scope"
2: "ng-isolate-scope"
length: 3

The classname1 refers to the classname I gave to directive. But that directive is not present in DOM. Still the $element.classList contains that classname.

Is it related to $scope.$destroy() issue?

What $destroy() do ?

The order of operations in your AngularJS directive is important because of the way jQuery implements the .remove() method. When you remove an element from the DOM using .remove() or .empty(), jQuery will clear out the event bindings and the data associated with the element so as to avoid memory leaks. This means that if you remove the element before you trigger the "$destroy" event, the element will be in a "sanitized state" by the time your $destroy event handler is executed.

and in your directive, you should call it like

ctrl.directive('directivename', function() {
    return function(scope, element, attributes) {        
        scope.$on('$destroy', function() {
            //Code to be execute just before destroying this directive or broadcast any mesage
        });
    };
});

You can use:

return{
controller:function($scope,$element,$rootScope){
  $scope.$on('$destroy',function(){
    /*adding and removing elemnts to dom */
  }
}
}

For animation if you are using any timer (like setInterval() or $interval of angular) then that needs to be stopped on destroy event. Since you have not used isolated scope for yoour directive so,you can register destroy method in controller itself.Clear the timer event in destroy method.

$scope.$on('$destroy',function(){
    /*clear your timer here
remove the element */
  }

If you have not stored your timer in any variable inside directive better you store it in parents scope ie in any variable of controller then clear it under destroy method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM