admin管理员组文章数量:1278910
I have the following use case - I provide a dialog service where I put a different content depending on the context. In the service method i manually pile a dom element and use it to display dialog using jquery ui. The code is the following:
var _view = jQuery('<div id="config-dialog"><span ng-include="\'' + $scope.configView + '\'" ng-controller="' + $scope.configController + '"></span></div>');
var _piled = $pile(_view.contents())($scope);
And then I fire a scope event that should be handled by a scope function defined in the controller
$scope.$broadcast('config-open', $scope.config);
then I open the dialog and the user performs something and closes the dialog. When the dialog gets closed i remove the "config-dialog" element from the DOM. Like this:
$(this).dialog("destroy");
jQuery('#config-dialog').remove();
However the next time the dialog gets opened and a new controller gets instantiated i see that the 'config-open' gets handled twice, when open the dialog again it gets handled 3 times. That means the scope attached to the ng-include that I dynamically create is not destroyed. I've debugged with Batarang and saw that really the child scope created by ng-include is not cleaned. AFAIK AngularJS scopes are associated to dom elements and when I remove the element, the scope should be garbage collected but this doesn't happen. My question is - is AngularJS supposed to clean up the scope in my case. What am I doing wrong and is there a more proper way to implement my use case?
I have the following use case - I provide a dialog service where I put a different content depending on the context. In the service method i manually pile a dom element and use it to display dialog using jquery ui. The code is the following:
var _view = jQuery('<div id="config-dialog"><span ng-include="\'' + $scope.configView + '\'" ng-controller="' + $scope.configController + '"></span></div>');
var _piled = $pile(_view.contents())($scope);
And then I fire a scope event that should be handled by a scope function defined in the controller
$scope.$broadcast('config-open', $scope.config);
then I open the dialog and the user performs something and closes the dialog. When the dialog gets closed i remove the "config-dialog" element from the DOM. Like this:
$(this).dialog("destroy");
jQuery('#config-dialog').remove();
However the next time the dialog gets opened and a new controller gets instantiated i see that the 'config-open' gets handled twice, when open the dialog again it gets handled 3 times. That means the scope attached to the ng-include that I dynamically create is not destroyed. I've debugged with Batarang and saw that really the child scope created by ng-include is not cleaned. AFAIK AngularJS scopes are associated to dom elements and when I remove the element, the scope should be garbage collected but this doesn't happen. My question is - is AngularJS supposed to clean up the scope in my case. What am I doing wrong and is there a more proper way to implement my use case?
Share Improve this question asked Sep 29, 2013 at 12:41 Adrian MitevAdrian Mitev 4,7524 gold badges33 silver badges53 bronze badges 1- 2 Do you have a fiddle/plunkr for this? There may be details we are missing. – Nikos Paraskevopoulos Commented Oct 1, 2013 at 15:13
3 Answers
Reset to default 4 +100The controller is only for the dialog content. OK and cancel buttons for the dialog are handled outside of the dialog content
I suppose your HTML looks like this:
<div class="dialog">
<div class="dialog-content" ng-controller="yourcontroller">
...your content here
</div>
<button id="btnClose">Close</button> //your button is outside your controller
</div>
Try: angular.element(domElement).scope()
Like this (using jquery with delegated event because you're creating your DOM dynamically):
$(document).on("click","#btnClose",function(){
var dialog = $(this).closest(".dialog");
//call this to destroy the scope.
angular.element(dialog.find(".dialog-content")[0]).scope().$destroy();
//or angular.element(dialog[0]).scope().$destroy(); depending on where you attach your scope.
//Destroy dialog
dialog.dialog("destroy");
dialog.remove();
});
When your dialog is closing, you should actually destroy the scope manually.
As an example, let's say you have a dom element in your dialog that has an ng-click:
<div class="dialog">
....
<a data-ng-click="closeDialog()">Close Me!</a>
....
</div>
Then in your controller you would wire up that ng click like so:
function myController($scope, ....){
....
$scope.closeDialog = function(){
$scope.$destroy();
//not to sure about the use of the word "this" here, but you should be able to figure out what element it is somehow
$(this).dialog("destroy");
jQuery('#config-dialog').remove();
}
....
}
The problem I think you're encountering is that you think by destroy the element the scope is destroyed. That's not true. You have to destroy the scope manually.
I'm going to do something I usually don't do and suggest you take a different approach altogether. Your problem most likely arises due to the bination of JQuery and Angular (haven't tried your code, but it seems like the most likely reason). Angular will loose track of stuff done outside the framework which is one of the reasons not to mix unless you really have to.
In this specific case, as far as I understand it, there is nothing that you couldn't do in Angular instead.
If I would do this, I would probably start by putting my dialog inside an ng-switch (which adds and removes things from the DOM just like your JQuery would), and then have my opening broadcast and the close button trigger the ng-switch criteria instead. Then you have a dialog that is added and removed form the DOM like you have it and this way you don't have to worry about syncing between Angular and Jquery.
And read the second part of this! I used to use Jquery all over the place in Angular before, then I read this post and stopped. Now everything tends to go much more smoothly :-)
Edit: A small example html. "dialog.template" in this example is a variable in the scope of DialogController that is set by the invoker.
<div ng-switch on="dialog_status">
<div ng-switch-when="open">
<div class="dialog" ng-controller="DialogController" ng-include="dialog.template">
Dialog will appear here
</div>
</div>
</div>
本文标签: javascriptAngularJS not cleaning child scope created by ngincludeStack Overflow
版权声明:本文标题:javascript - AngularJS not cleaning child scope created by ng-include - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741303316a2371222.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论