我正在尝试在angularjs中实现一个插件系统,允许用户配置他们将在某个页面上看到的“小部件”。每个小部件由控制器和模板(url)定义。是否可以创建一个实例化控制器的指令,使用模板调用它并转换结果内容?
目标是这样的:
<div class="widget" ng-repeat="widget in widgets">
<widget controller="widget.controller" templateUrl="widget.templateUrl"></widget>
</div>
答案 0 :(得分:74)
有两种方法可以做到这一点;一个使用已经可用的辅助指令(如ngInclude
和ngController
),第二个是手动;手动版可能更快,但我无法确定。
简单方法:
简单的方法是简单地创建一个包含ngController
和ngInclude
属性的新元素,将其附加到指令的元素,然后$compile
它:
var html = '<div ng-controller="'+ctrl+'" ng-include="'+tpl+'"></div>';
element.append(html);
$compile( element.contents() )( scope );
手动方式:
手动方式是依次执行这些指令本身的操作;这个逻辑与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 );
});
(请注意,这里没有垃圾收集,如果小部件发生变化,您需要实现垃圾收集)
这是一个展示两种方法的Plunker:http://plnkr.co/edit/C7x9C5JgUuT1yk0mBUmE?p=preview