AngularJS手动渲染控制器和模板

Lor*_*nVS 39 angularjs angularjs-directive

我正在尝试在angularjs中实现一个插件系统,允许用户配置他们将在某个页面上看到的"小部件".每个小部件由控制器和模板(url)定义.是否可以创建一个实例化控制器的指令,使用模板调用它并转换结果内容?

目标是这样的:

<div class="widget" ng-repeat="widget in widgets">
    <widget controller="widget.controller" templateUrl="widget.templateUrl"></widget>
</div>
Run Code Online (Sandbox Code Playgroud)

Jos*_*ler 74

有两种方法可以做到这一点; 一个使用已经可用的辅助指令(如ngIncludengController),第二个是手动; 手动版可能会更快,但我不能确定.

简单方法:

简单的方法是使用ngControllerngInclude属性创建一个新元素,将它附加到指令的元素,然后$compile:

var html = '<div ng-controller="'+ctrl+'" ng-include="'+tpl+'"></div>';
element.append(html);
$compile( element.contents() )( scope );
Run Code Online (Sandbox Code Playgroud)

手动方式:

手动方式是依次执行这些指令本身的操作; 这种逻辑非常类似ngView(尽管没有复杂性).我们获取模板,将其存储在中$templateCache,然后将其附加到DOM.我们创建一个新的子范围并使用它实例化提供的控制器并将该控制器分配给该元素.最后,我们$compile:

$http.get( tpl, { cache: $templateCache } )
.then( function( response ) {
  templateScope = scope.$new();
  templateCtrl = $controller( ctrl, { $scope: templateScope } );
  element.html( response.data );
  element.children().data('$ngControllerController', templateCtrl);
  $compile( element.contents() )( templateScope );
});
Run Code Online (Sandbox Code Playgroud)

(请注意,此处没有垃圾收集,如果窗口小部件发生更改,您需要实现)

这是一个展示两种方法的Plunker:http://plnkr.co/edit/C7x9C5JgUuT1yk0mBUmE?p=preview

  • 这太棒了.但是,我不明白将控制器与`'$ ngControllerController'..data()键相关联的内容.我看到它应该将控制器与元素的子节点相关联(反之亦然),但是通过Angular源,我看不出它是如何发生的,据我所知,Plnkr仍然按预期工作那条线注释掉了.任何人都可以解释这条线的作用吗? (5认同)