动态加载控制器和ng-include

and*_*o1d 30 angularjs

目前我有一个带侧边栏的应用程序,侧边栏ng-include根据用户选择的操作加载不同的html模板.这是一个与地图相关的应用程序,例如,如果用户选择"添加腿"按钮,它将add_leg.html使用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>
Run Code Online (Sandbox Code Playgroud)

这一切都很好,并且按照需要工作,但目前我的应用程序只使用一个控制器(MainCtrlin js/controllers.js),它开始变得非常混乱.我现在有很多方法,因为应用功能正在扩展.我想将控制器分成多个控制器,同时保留这个侧边栏功能.

我希望MainCtrl作为主控制器控制侧边栏模板的加载(通过更改sidebar_template指向文件目标的变量),我希望它控制一些全局地图相关的方法(比如从坐标中获取郊区名称,等等).

我试图像这样拆分它:

controllers/js/main.js - MainCtrl
controllers/js/legs.js - LegCtrl
controllers/js/routes.js - RouteCtrl
Run Code Online (Sandbox Code Playgroud)

我希望LegCtrlRouteCtrl继承,MainCtrl所以我可以访问它的范围和方法,这一切都很好.但现在的问题是如何根据所需的功能将控制器动态加载到侧边栏div上.最初我的所有方法都在MainCtrl,并且在包围div的包围div上(参见上面的例子),所以这不是问题.

例如,假设我按"添加腿"按钮,这将需要调用addLegLegCtrl,但LegCtrl没有加载上的应用程序,因此它不能访问的方法.我可以保留addLeg()在里面MainCtrl,并让它更改sidebar_template变量以加载模板,但模板中的任何内容都不起作用,因为它从LegCtrl现在内部调用方法.

我需要以某种方式动态加载侧边栏的ng-includediv 上的控制器,这可能是这样的:

// 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>
Run Code Online (Sandbox Code Playgroud)

在上面的非工作示例中,您可以看到我想到的可能的解决方案,但我需要LegCtrl是实际的控制器功能,而不是对象(用于ng-controller工作).我还需要一些方法来调用addLegLegCtrlMainCtrl.addLeg(可能使用广播?).

如果有人能指出我正确的方向,那将是伟大的.对于这篇巨大的帖子感到抱歉,它需要一些解释才能使它变得连贯.希望这是有道理的.谢谢.

更新:我想我找到了一个使用服务作为导航控件的解决方案(它将加载相关模板并向动态加载的新控制器广播一个事件,告诉它要执行哪个函数):

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

只是试图现在测试这个想法,但广播.on不起作用.我认为这是因为广播在模板加载之前触发.我怎样才能解决这个问题?这对我正在做的事情是一个很好的解决方案吗?

Cha*_*ani 12

如果我已经正确理解你可以尝试创建一个模板视图专门创建一个新的腿.

从主控制器实现一些逻辑来显示模板

$scope.addLeg=function() {
   $scope.showAddLeg=true;
}
Run Code Online (Sandbox Code Playgroud)

AddLeg模板视图将加载控制器,从而提供实际添加新支路的机制.模板看起来像

<script type="text/ng-template" class="template" id="addLegTemplate">
    <div ng-controller='LegsController'>
    <!--html for adding a new leg-->
    </div>
</script>
Run Code Online (Sandbox Code Playgroud)

您可以使用ng-if + ng-include在主html中包含此模板.

<div ng-if='showAddLeg'><div ng-include='addLegTemplate'/></div>
Run Code Online (Sandbox Code Playgroud)

基本上,您可以创建多个视图并绑定到同一个控制器(但实例会有所不同).在这种情况下,LegsController可以绑定到多个视图以支持完整功能.


Cra*_*aig 5

我喜欢这种数据驱动的场景,只需操作模板中的行:

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

和标记:

<div ng-repeat="template in templates" ng-include="template.url"></div>
Run Code Online (Sandbox Code Playgroud)

要添加或删除视图,只需修改模板等即可!如果您需要更多控制器代码,则可以在include中包含指向脚本的链接.我猜在部分视图本身中绑定到数据可能会有并发症,但是$ compile应该解决这些问题.