我有以下用例 - 我提供了一个对话服务,我根据上下文放置了不同的内容。在服务方法中,我手动编译dom元素并使用它来显示使用jquery ui的对话框。代码如下:
var _view = jQuery('<div id="config-dialog"><span ng-include="\'' + $scope.configView + '\'" ng-controller="' + $scope.configController + '"></span></div>');
var _compiled = $compile(_view.contents())($scope);
然后我触发一个范围事件,该事件应由控制器中定义的范围函数处理
$scope.$broadcast('config-open', $scope.config);
然后我打开对话框,用户执行某些操作并关闭对话框。当对话框关闭时,我从DOM中删除“config-dialog”元素。像这样:
$(this).dialog("destroy");
jQuery('#config-dialog').remove();
然而,下次打开对话框并实例化新控制器时,我会看到'config-open'被处理两次,再次打开对话框时会被处理3次。这意味着我动态创建的ng-include附加的范围不会被破坏。我已经使用Batarang进行了调试,发现实际上没有清除ng-include创建的子范围。 AFAIK AngularJS范围与dom元素相关联,当我删除元素时,范围应该是垃圾收集,但这不会发生。 我的问题是 - AngularJS应该在我的案例中清理范围。我做错了什么,是否有更合适的方式来实现我的用例?
答案 0 :(得分:4)
当您的对话框关闭时,您实际上应该手动销毁范围。
举个例子,假设你的对话框中有一个dom元素有一个ng-click:
<div class="dialog">
....
<a data-ng-click="closeDialog()">Close Me!</a>
....
</div>
然后在您的控制器中,您可以像这样连接点击:
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();
}
....
}
我认为你遇到的问题是你认为通过破坏范围被破坏的元素。这不是真的。你必须手动销毁范围。
答案 1 :(得分:4)
控制器仅用于对话框内容。确定并取消按钮 对话框在对话框内容之外处理
我认为您的HTML看起来像这样:
<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>
尝试:angular.element(domElement).scope()
像这样(使用带有委托事件的jquery,因为你是动态创建DOM):
$(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();
});
答案 2 :(得分:1)
我会做一些我通常不做的事情,并建议你采取不同的方法。你的问题最有可能是由于JQuery和Angular的结合(没有尝试过你的代码,但似乎是最可能的原因)。 Angular会忽略在框架外完成的事情,这是除非你真的需要,否则不混合的原因之一。
在这种特殊情况下,据我所知,在Angular中你无法做任何事情。
如果我这样做,我可能会首先把我的对话框放在ng-switch(它就像你的JQuery那样添加和删除DOM中的东西),然后让我的开放广播和关闭按钮而是触发ng-switch标准。然后你就有了一个像DOM那样在DOM中添加和删除的对话框,这样你就不必担心Angular和Jquery之间的同步了。
阅读this的第二部分!之前我曾经在Angular中使用Jquery,然后我读了这篇文章并停了下来。现在一切都变得顺利了: - )
编辑:一个小例子html。此示例中的“dialog.template”是由调用者设置的DialogController范围内的变量。
<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>