我想在angular.js中创建一个视图,在其中添加动态模板集,每个模板都包装在一个指令中。伪指令名称对应于一组对象中的某些字符串属性。我需要一种添加指令的方式,而无需事先知道将需要哪些指令。
该项目将Angular 1.5与webpack结合使用。
这是代码的简化版本:
对象集:
$scope.items = [
{ name: "a", id: 1 },
{ name: "b", id: 2 }
]
指令:
angular.module('myAmazingModule')
.directive('aDetails', () => ({
scope: false,
restrict: 'E',
controller: 'myRavishingController',
template: require("./a.html")
}))
.directive('bDetails',() => ({
scope: false,
restrict: 'E',
controller: 'myRavishingController',
template: require("./b.html")
}));
视图:
<li ng-repeat="item in items">
<div>
<{{item.name}}-details/>
</div>
</li>
,以便最终呈现的视图如下所示:
<li ng-repeat="item in items">
<div>
<a-details/>
</div>
<div>
<b-details/>
</div>
</li>
我该怎么做?
我不介意其他方法,只要我可以内嵌细节模板,然后通过http分别获取它们即可。
答案 0 :(得分:0)
使用ng-include
:
<li ng-repeat="item in items">
<div ng-controller="myRavishingController"
ng-include="'./'+item.name+'.html'">
</div>
</li>
我想内联它以避免http呼叫。
通过以下两种方式之一将模板直接加载到模板缓存中,从而避免http调用:
$templateCache
服务。有关更多信息,请参见
答案 1 :(得分:0)
您可以使用以下指令添加任何html:
const el = $compile(myHtmlWithDirectives)($scope);
$element.append(el);
但是通常这不是最好的方法,我将使用ng-include
(为您实际调用$compile
)给出更详细的答案:
添加模板,例如在module.run中:[您也可以在html中添加模板,但是当需要在多个位置使用它们时,我更喜欢直接添加它们]
app.module('myModule').run($templateCache => {
$templateCache.put('tplA', '<a-details></a-details>'); // or webpack require
$templateCache.put('tplB', '<b-details></b-details>');
$templateCache.put('anotherTemplate', '<input ng-model="item.x">');
})
您现在的模型是:
$scope.items = [
{ name: "a", template: 'tplA' },
{ name: "b", template: 'tplB' },
{ name: "c", template: 'anotherTemplate', x: 'editableField' }
]
和html:
<li ng-repeat="item in items">
<div ng-include="item.template">
</div>
</li>
答案 2 :(得分:0)
为了使用动态指令,您可以像在此plunkr中一样创建一个自定义指令:
https://plnkr.co/edit/n9c0ws?p=preview
这是所需指令的代码:
app.directive('myProxy', function($compile) {
return {
template: '<div>Never Shown</div>',
scope: {
type: '=',
arg1: '=',
arg2: '='
},
replace: true,
controllerAs: '$ctrl',
link: function($scope, element, attrs, controller, transcludeFn) {
var childScope = null;
$scope.disable = () => {
// remove the inside
$scope.changeView('<div></div>');
};
$scope.changeView = function(html) {
// if we already had instanciated a directive
// then remove it, will trigger all $destroy of children
// directives and remove
// the $watch bindings
if(childScope)
childScope.$destroy();
console.log(html);
// create a new scope for the new directive
childScope = $scope.$new();
element.html(html);
$compile(element.contents())(childScope);
};
$scope.disable();
},
// controller is called first
controller: function($scope) {
var refreshData = () => {
this.arg1 = $scope.arg1;
this.arg2 = $scope.arg2;
};
// if the target-directive type is changed, then we have to
// change the template
$scope.$watch('type', function() {
this.type = $scope.type;
refreshData();
var html = "<div " + this.type + " ";
html += 'data-arg1="$ctrl.arg1" ';
html += 'data-arg2="$ctrl.arg2"';
html += "></div>";
$scope.changeView(html);
});
// if one of the argument of the target-directive is changed, just change
// the value of $ctrl.argX, they will be updated via $digest
$scope.$watchGroup(['arg1', 'arg2'], function() {
refreshData();
});
}
};
});
总体思路是:
data-type
能够指定要显示的指令的名称type
发生了变化,我们将重写html以调用目标指令如果您的目标指令都共享相同的参数,则此实现是可以的。我没有走得更远。
如果您想对其进行更动态的修改,我想您可以设置scope: true
并必须使用attrs来找到传递给目标指令的参数。
此外,您应该使用https://www.npmjs.com/package/gulp-angular-templatecache之类的模板来转换可连接到javascript应用程序中的代码中的模板。这样会更快。