2013-09-29 21 views
4

創建的子範圍我有以下用例 - 我提供了一個對話服務,我根據上下文放置了不同的內容。在service方法中,我手動編譯一個dom元素並使用它來顯示使用jquery ui的對話框。代碼如下:AngularJS不清理由ng-include

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應該在我的情況下清理範圍。我做錯了什麼,是否有更適當的方式來實施我的用例?

+2

你有這個小提琴/ plunkr嗎?可能有我們缺少的細節。 –

回答

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

這是正確的,但有沒有教程/博客文章描述範圍以及如何正確管理它們,即使對於動態內容。 –

+0

@AdrianMitev:我在其官方網站http://angularjs.org/上了解了所有關於角度js的信息。(我不知道是否有更好的網站)。有很多信息可以找到。像http://docs.angularjs.org/guide/,http://docs.angularjs.org/api/,http://blog.angularjs.org/,...在你的情況下,你可以找到信息在http://docs.angularjs.org/api/ng.$compile和http://docs.angularjs.org/guide/scope –

4

當對話框關閉時,實際上應該手動銷燬作用域。

舉個例子,假設你有你的對話框中,有一個DOM元素的NG-點擊:

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

我認爲你遇到的問題是你認爲通過銷燬範圍被銷燬的元素。這不是真的。您必須手動銷燬示波器。

+0

這對我不起作用,因爲控制器僅用於對話內容。對話框中的確定和取消按鈕在對話框內容之外進行處理。是否有一個文檔描述了scopoe何時被取消以及關於控制範圍生命週期的最佳實踐? –

+1

小心把js小提琴放在一起?我想看看你是如何構建密切的部分。 –

1

我要去做我通常不會做的事情,並建議你採取不同的方法一起。你的問題最有可能是由於JQuery和Angular的組合(沒有試過你的代碼,但它似乎是最可能的原因)。除非你真的需要,否則Angular會丟失在框架之外完成的任務,這是不混合的原因之一。

在這個特定的情況下,據我所知,沒有什麼是你在Angular中不能做的。

如果我這樣做,我可能會首先將我的對話框放在ng-switch(它會像JQuery那樣添加和刪除東西),然後讓我的開放廣播和關閉按鈕觸發ng取而代之的是切換標準。然後你有一個對話框,可以像你一樣添加和刪除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> 
+0

我的對話框必須顯示不同類型的視圖與特定的控制器。你如何推薦使用ng-switch來做到這一點? –

+0

假設您已經有了可以包含的模板(看起來像您從emaple獲得的模板),您可以像現在一樣使用ng-include。您切換的內容可以包含一個包含ng-include = {{some_scope_parameter}}的div。 –