2013-07-23 51 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中包含一个指向脚本的链接。我猜可能在部分视图本身中绑定数据可能会有复杂性,但$编译应该可以解决这些问题。