-
Notifications
You must be signed in to change notification settings - Fork 27.4k
component's controller $onDestroy hook is not called on manual $scope.$destroy from inside the controller #14376
Comments
This seems to happen only in this very specific case where you destroy the controller scope from inside a timeout in the controller. I guess this is a contrived example. What's the real use case you have? Why would you destroy the scope from inside the controller? |
So this happens because there is a mismatch between the scopes. The way I see it, we bind our internal $onDestroy on the compile scope (that scope that is passed to compile), but the scope that is passed to the controller is a child of this scope. So when you destroy the scope inside the controller, you are not triggering the destroy handler on its parent.
@petebacondarwin @gkalpak do you have an idea what's going on here? |
As far as the example given is concerned, I would say that this is invalid. Destroying the inner scope has got nothing to do with destroying the component itself. The component exists in a scope, which happens to be the compile scope. Assuming you are not doing anything naughty then that scope is destroyed when the component's element is destroyed. See the following for a realistic example: http://plnkr.co/edit/578Yvv0XU3brYXwco4h5?p=preview |
Dynamically created directives as |
@petebacondarwin Hm, can you review issue resolution due to real world example that i described above? My jsfiddle from first post was about bug repoducing, not about real case from project. This problem is actual for dinamically created directives. |
True. I just moved the code from the former to the latter without a second thought. And only now that I read this issue I realized that it's not that simple. |
Not sure if related but selecting a directive node in Chrome devtools and executing |
So:
|
Why does removing the element from the DOM not trigger I'm subscribing to an event in my component and I want to unsubscribe when it's destroyed (removed from the DOM), but |
No need to be flippant :-) As it clearly states in the docs: https://docs.angularjs.org/api/ng/service/$compile
So, Manually removing an element from the DOM without dealing with its DOM will lead to memory leaks, since the component bindings will have created watches on the containing scope. The correct way to add and remove things from the DOM is demonstrated inside directives such as |
@petebacondarwin please look at jsfiddle from first post - there is explicit |
Ok, I had misunderstood this comment to mean that To anyone else having this problem: update to 1.5.3 or later. |
@CarlLeth, the @artaommahe, your example shows |
Closing since everything seems to work as expected (and we didn't hear from the OP in a while). |
Hi, in this days I stumbled in the same problem @artaommahe http://jsfiddle.net/zaquas/sn2br6ka/ (try move the windows, close it and watch in console, use the right button mouse to create new o push the button... the new window will be create in a stack, move for clear) I don't know if this is the right way for destroy the dinamic component, but it is the best that I can do. I would not use the "ng-if" directive as suggest @petebacondarwin because I would use the two component "myCanvas" and "myWindow" also in plain html, like: Something here without polluting the tag "my-window" with "ng-if" directive connect with $ctrl of my-canvas, that some my user may not understand... The problem now is that the componet in plain html inside my-canvas is wrap with the tag and the other inject with the button "add win" is without this... I would have the windows tags in the same level. I would note that i destroy the parent scope of window, that is the child scope of canvas. Is right? Thanks for read this. |
Other problem... http://jsfiddle.net/zaquas/wezb90b1/ Try to add item, close it and watch in console But now i found something of interest... The ng-click="$ctrl.close()" bind the call with the dom event, so when I click it, the parent $scope is destroyed, so the child $scope, but the bind remain in the dom.
Why the $ctrl is not destroyed? Obviously if you uncomment the code perhaps this good link http://www.bennadel.com/blog/2883-how-the-destroy-event-affects-the-scope-tree-in-angularjs.htm has answered the question |
@szaccaria - so from looking at your first fiddle, I would say that you are not using Angular correctly here. You should not be adding elements dynamically inside your Of course this doesn't quite help with the one you passed in via transclusion but that can be fixed... |
I'm having a similar problem, but with DOM. Not using routing but ng-include, when I switch between views a component DOM remains from the previous view, even tough the $onDestroy event was called. |
@khullah can you please open a new issue and provide a running example of your problem? |
Hi, thanks for the reply. So, I build a plunker but the problem wasn't reproduced. Digging it further I found out that the succeeding view also had the same component somewhere, but he wasn't initializing properly, masking the real problem. So not related to this thread, sorry. |
If we call
$scope.$destroy()
then$onDestroy
hook never fires,$scope.$on('$destroy')
works welle.x. watch in console https://jsfiddle.net/artaommahe/agL5zuzf/1/
on parent scope destroy both hooks work well
The text was updated successfully, but these errors were encountered: