AngularJS:动态分配从纳克重复控制器(AngularJS: dynamically assi

2019-07-05 19:04发布

我试图动态分配控制器像这样包含的模板:

<section ng-repeat="panel in panels">
    <div ng-include="'path/to/file.html'" ng-controller="{{panel}}"></div>
</section>

但是,角抱怨{{panel}}是不确定的。

我猜测, {{panel}} 尚未确定(因为我可以附和了{{panel}}在模板中)。

我见过很多人树立榜样ng-controller等于一个变量,像这样: ng-controller="template.ctrlr" 。 但是,如果没有创建重复concurrant循环,我无法弄清楚如何让价值{{panel}}可用时ng-controller需要它。

PS我也试着设置ng-controller="{{panel}}"在我的模板(认为它必须那么已经解决),但没有骰子。

Answer 1:

你的问题是,NG-控制器应指向控制器本身,没有与控制器的名字只是字符串。

所以,你可能要定义$ scope.sidepanels与指针控制器,这样的事情,也许阵:

$scope.sidepanels = [Alerts, Subscriptions];

这里是JS提琴工作实例http://jsfiddle.net/ADukg/1559/

不过,我觉得很奇怪这一切的情况下,您可能要设置控制器在ngRepeat。



Answer 2:

动态地设置在一个模板控制器,它有助于必须连接到控制器的构造函数的引用。 对于控制器的构造函数是你传递给功能controller()角的方法模块API 。

有了这个帮助,因为如果传递给字符串ngController指令不是注册的控制方的名称,然后ngController将字符串作为表达对目前的范围进行评估。 这个范围表达需要评估到控制器构造函数

例如,假设角相遇在模板以下几点:

ng-controller="myController"

如果与名字没有控制器myController注册,然后将角度看$scope.myController当前包含控制器。 如果该键在存在范围和对应的值是控制器的构造 ,则控制器将被使用。

这在中提到ngController文档中其参数值的描述:“全局可访问的构造函数,或在当前范围的计算结果为一个构造函数表达式的名称。” 在角源代码代码的注释中详细阐明了这一点, 在这里src/ng/controller.js

默认情况下,角不会很容易地访问连接到控制器的构造。 这是因为当你注册使用一个控制器controller()角的方法模块API ,它隐藏你通过它在一个私有变量的构造。 你可以在这里看到$ ControllerProvider源代码 。 (该controllers在这个代码变量是变量私人到$ControllerProvider 。)

我对这个问题的解决方案是创建一个名为通用助手服务registerController登记控制器。 注册控制器时,该服务公开两个控制器控制器构造函数。 这允许控制器两者在正常的方式,动态地使用。

下面是代码,我写了registerController做这个服务:

var appServices = angular.module('app.services', []);

// Define a registerController service that creates a new controller
// in the usual way.  In addition, the service registers the
// controller's constructor as a service.  This allows the controller
// to be set dynamically within a template.
appServices.config(['$controllerProvider', '$injector', '$provide',
  function ($controllerProvider, $injector, $provide) {
    $provide.factory('registerController',
      function registerControllerFactory() {
        // Params:
        //   constructor: controller constructor function, optionally
        //     in the annotated array form.
        return function registerController(name, constructor) {
            // Register the controller constructor as a service.
            $provide.factory(name + 'Factory', function () {
                return constructor;
            });
            // Register the controller itself.
            $controllerProvider.register(name, constructor);
        };
    });
}]);

下面是使用该服务来注册的控制器的一个示例:

appServices.run(['registerController',
  function (registerController) {

    registerController('testCtrl', ['$scope',
      function testCtrl($scope) {
        $scope.foo = 'bar';
    }]);

}]);

上面的代码注册名称下的控制器testCtrl ,这也暴露了控制器的构造函数的调用的服务testCtrlFactory

现在,你可以在模板无论是在平时的fashion--使用控制器

ng-controller="testCtrl"

或dynamically--

ng-controller="templateController"

对于后者的工作,你必须在你当前范围如下:

$scope.templateController = testCtrlFactory


Answer 3:

我相信你,因为你定义这样的(就像我以前做)你的控制器有这个问题:

app.controller('ControllerX', function() {
    // your controller implementation        
});

如果是这样的话,你不能简单地用引用ControllerX因为控制器实现(或“类”,如果你要称呼它)是不是在全球范围内(而不是将其存储在应用$controllerProvider )。

我建议你使用模板,而不是动态分配控制的引用(甚至是手动创建)。

控制器

var app = angular.module('app', []);    
app.controller('Ctrl', function($scope, $controller) {
    $scope.panels = [{template: 'panel1.html'}, {template: 'panel2.html'}];        
});

app.controller("Panel1Ctrl", function($scope) {
    $scope.id = 1;
});
app.controller("Panel2Ctrl", function($scope) {
    $scope.id = 2;
});

模板(嘲笑)

<!-- panel1.html -->
<script type="text/ng-template" id="panel1.html">
  <div ng-controller="Panel1Ctrl">
    Content of panel {{id}}
  </div>
</script>

<!-- panel2.html -->
<script type="text/ng-template" id="panel2.html">
  <div ng-controller="Panel2Ctrl">
    Content of panel {{id}}
  </div>
</script>

视图

<div ng-controller="Ctrl">
    <div ng-repeat="panel in panels">
        <div ng-include src="panel.template"></div>        
    </div>
</div>

的jsfiddle: http://jsfiddle.net/Xn4H8/



Answer 4:

另一种方法是不使用NG-重复,而是一个指令,它们编成存在。

HTML

<mysections></mysections>

指示

angular.module('app.directives', [])
    .directive('mysections', ['$compile', function(compile){
        return {
            restrict: 'E',
            link: function(scope, element, attrs) {
                for(var i=0; i<panels.length; i++) {
                    var template = '<section><div ng-include="path/to/file.html" ng-controller="'+panels[i]+'"></div></section>';
                    var cTemplate = compile(template)(scope);

                    element.append(cTemplate);
                }
            }
        }
    }]);


Answer 5:

好吧,我觉得这里最简单的解决办法是在你的文件的模板明确定义控制器。 比方说u有一个数组:

$scope.widgets = [
      {templateUrl: 'templates/widgets/aWidget.html'},
      {templateUrl: 'templates/widgets/bWidget.html'},
];

然后在你的HTML文件:

<div ng-repeat="widget in widgets">
    <div ng-include="widget.templateUrl"></div>
</div>

而解决方案aWidget.html:

<div ng-controller="aWidgetCtrl">
   aWidget
</div>

bWidget.html:

<div ng-controller="bWidgetCtrl">
   bWidget
</div>

就那么简单! 你只要在你的模板定义控制器名称。 既然你定义控制器为bmleite说:

app.controller('ControllerX', function() {
// your controller implementation        
});

那么这是我能想出的最好的解决方法。 这里唯一的问题是,如果u有像50个控制器,日子会把你必须明确地定义他们每个模板,但我猜ü了,因为你有一个NG重复与控制器通过手工设置为做到这一点呢。



文章来源: AngularJS: dynamically assign controller from ng-repeat