2013-07-23 381 views
29

目前我有一個具有側邊欄的應用程序,側邊欄根據用戶選擇的操作使用ng-include加載不同的html模板。這是一個與地圖相關的應用程序,因此,例如,如果用戶選擇「添加腿」按鈕,它會在add_leg.html模板加載到使用ng-include側邊欄:動態加載控制器和ng-include

// The Javascript code: 
$scope.addLeg = function() { 
    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  
} 

// Simplified example of HTML: 
<html> 
<div ng-app="MyApp" ng-controller="MainCtrl"> 
    <a ng-click="addLeg()">Add Leg</a> 
    <a ng-click="addRoute()">Add Route</a> 
    <a ng-click="editLeg()">Edit Leg</a> 
    <a ng-click="editRoute()">Edit Route</a> 
    ... 

    <div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
     <div ng-include src="sidebar_template"></div> 
    </div> 

    <google-map></google-map> 
</div> 

這是一切都很好,並根據需要工作,但目前我的應用程序只使用一個控制器(MainCtrljs/controllers.js),它開始變得非常混亂。現在我有很多方法,因爲應用程序功能正在擴展。我想將我的控制器分成多個控制器,同時保留此側邊欄功能。

我想有MainCtrl作爲控制欄模板的加載(通過改變sidebar_template變量指向的文件目的地)主控制器,我想它來控制一些全球地圖相關的方法(如從座標獲取郊區名稱等)。

我試着像這樣分割:

controllers/js/main.js - MainCtrl 
controllers/js/legs.js - LegCtrl 
controllers/js/routes.js - RouteCtrl 

我想LegCtrlRouteCtrl繼承MainCtrl所以我可以訪問它的範圍和方法,這是所有罰款。但現在的問題是,如何根據需要哪些功能將控制器動態加載到側欄div上。最初,我所有的方法都在MainCtrl中,並且位於邊欄div周圍的包裝div(請參閱上面的示例),所以這不是問題。

例如,假設我按「添加腿」按鈕,這將需要調用addLegLegCtrl,但LegCtrl沒有加載上的應用程序,因此它不能訪問的方法。我可以將addLeg()保存在MainCtrl之內,並將其更改爲sidebar_template變量以加載該模板,但模板中的任何內容都不起作用,因爲它現在正在調用LegCtrl之內的方法。

我需要也許莫名其妙動態加載側邊欄上的ng-include DIV控制器,是這樣的:

// MainCtrl 
$scope.addLeg = function() { 
    $scope.required_controller = LegCtrl; 

    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  

    LegCtrl.addLeg(); 
} 

<div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
    <div ng-include src="sidebar_template" ng-controller="{{required_controller}}"></div> 
</div> 

在非工作上面的例子,你可以看到一個可能的解決方案我想過的,但我需要LegCtrl作爲實際的控制器功能,而不是一個對象(ng-controller工作)。我還需要一些方法從MainCtrl.addLeg(可能使用廣播?)撥打LegCtrl上的addLeg

如果任何人都可以指出我的方向會很棒。對於這篇巨大的文章感到抱歉,它需要一些解釋才能使其一致。希望它是有道理的。謝謝。

更新:我想我已經找到了一個使用服務作爲導航控件的解決方案(它將加載相關模板並向正在動態加載的新控制器廣播一個事件,以告訴它要執行的功能):

http://plnkr.co/edit/Tjyn1OiVvToNntPBoH58?p=preview

只是想出來,現在來測試這個想法,但廣播.on不起作用。我認爲這是因爲廣播在模板加載之前觸發。我怎樣才能解決這個問題?這是我正在做的一個很好的解決方案嗎?

+0

我看到你的潛水員並編輯它以包含控制檯消息。它會告訴你事件首先發布,然後監聽器開始收聽。發生這種情況是因爲每個事物都是在角應用程序中加載的。 http://plnkr.co/edit/rWZ3x2Jzk9EV3OpD1HF1?p=preview –

回答

12

如果我正確理解了你,你可以嘗試創建一個模板視圖來創建一個新的腿。

從主控制器實現一些邏輯展現模板

$scope.addLeg=function() { 
    $scope.showAddLeg=true; 
} 

的AddLeg模板視圖將加載控制器,並因此提供一種機制來實際添加新的腿。該模板看起來像

<script type="text/ng-template" class="template" id="addLegTemplate"> 
    <div ng-controller='LegsController'> 
    <!--html for adding a new leg--> 
    </div> 
</script> 

您可以使用ng-if + ng-include在您的main html中包含此模板。

<div ng-if='showAddLeg'><div ng-include='addLegTemplate'/></div> 

基本上可以創建多個視圖並綁定到相同的控制器(但實例會有所不同)。在這種情況下,LegsController可綁定到多個視圖以支持完整的功能。

+0

這個問題是,如果我加載了與腿功能相關的新模板(也許在addLeg模板上是一個加載editLeg模板的按鈕),何時他們切換模板,它將在新控制器中擁有自己的控制器定義(從而丟失範圍,所有狀態變量將丟失)。 – andro1d

+0

您可以通過將模型保存在控制器之外並將其作爲ng-init的一部分傳遞來共享模型。 – Chandermani

+0

嗨Chandermani,你可以看看我的更新?謝謝。 – andro1d

4

我叉你plunkr演示爲一體,我認爲確實你找什麼:http://plnkr.co/edit/whsjBT?p=preview

這表明一個事件被廣播從一個控制器到另一個第二控制器之後(在我們的例子LegCtrl這裏)通過ng-include加載並傳遞數據。

我使用$includeContentLoaded來自ng-include事件來延遲廣播事件,直到加載了add_leg.html的角度報告。此外,我認爲有一些問題,你是如何使用$broadcast() ......這是第一個參數是一樣$on()用於LegCtrl

另一個想法是簡單地使用你的Navigation服務本身之間共享狀態考慮一個控制器是否適合您的情況。

+0

這正是我所尋找的。謝謝一堆! –

5

我喜歡這種數據驅動的情況下,只操縱行的模板:

$scope.templates = [ 
    { name: 'include1.html', url: 'partials/include1.html' } 
]; 
$scope.addTemplate = function(name, url) { 
    $scope.templates.push({ name: name, url: url }); 
}; 

和標記:

<div ng-repeat="template in templates" ng-include="template.url"></div> 

要添加或刪除的意見,只是修改模板等瞧!如果你需要更多的控制器代碼,那麼你可以在include中包含一個指向腳本的鏈接。我猜可能在部分視圖本身中綁定數據可能會有複雜性,但$編譯應該可以解決這些問題。