5

我有以下用例 - 我提供了一个对话服务,我根据上下文放置不同的内容。在服务方法中,我手动编译了一个 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();

但是,下次打开对话框并实例化一个新控制器时,我看到“配置打开”被处理了两次,当再次打开对话框时,它被处理了 3 次。这意味着附加到我动态创建的 ng-include 的范围不会被破坏。我用 Batarang 进行了调试,发现 ng-include 创建的子范围确实没有被清理。AFAIK AngularJS 范围与 dom 元素相关联,当我删除元素时,范围应该被垃圾收集,但这不会发生。我的问题是 - AngularJS 是否应该在我的情况下清理范围。我做错了什么,有没有更合适的方法来实现我的用例?

4

3 回答 3

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();
});
于 2013-10-05T08:20:18.393 回答
4

当您的对话框关闭时,您实际上应该手动销毁范围。

例如,假设您的对话框中有一个 dom 元素,该元素具有 ng-click:

<div class="dialog">
    ....
    <a data-ng-click="closeDialog()">Close Me!</a>
    ....
</div>

然后在你的控制器中,你会像这样连接那个 ng click:

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();
    }
    ....
}

我认为您遇到的问题是您认为通过破坏元素来破坏范围。这不是真的。您必须手动销毁范围。

于 2013-10-01T16:00:53.707 回答
1

我将做一些我通常不做的事情,并建议您完全采用不同的方法。您的问题很可能是由于 JQuery 和 Angular 的结合而出现的(没有尝试过您的代码,但这似乎是最可能的原因)。Angular 将失去对框架外完成的事情的跟踪,这是除非你真的必须这样做,否则不要混合的原因之一。

在这种特定情况下,据我所知,在 Angular 中没有什么是你不能做的。

如果我这样做,我可能会首先将我的对话框放在一个ng-switch中(就像你的 JQuery 一样从 DOM 中添加和删除东西),然后让我的打开广播和关闭按钮触发 ng-switch而是标准。然后你就有了一个从 DOM 中添加和删除的对话框,就像你拥有它一样,这样你就不必担心 Angular 和 Jquery 之间的同步。

并阅读本文的第二部分!我以前在 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>
于 2013-10-07T09:13:33.877 回答