基本上,我在一个指令的编译函数中使用了两个模板。 我在指令的编译阶段一次性编译它们(通过$ compile)。 在指令的链接阶段,我观察范围变量并将一个或另一个编译模板应用于范围。
testApp.directive('testField', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: true,
compile: function(tElement, tAttrs) {
var viewFn = $compile("<div>View: <span ng-repeat='x in [1,2,3]'>{{x}}</span></div>");
var editFn = $compile("<div>Edit: <span ng-repeat='x in [4,5,6]'>{{x}}</span></div>");
return function (scope, element, attrs) {
var innerScope = null;
scope.$watch("mode", function (mode) {
if (innerScope) innerScope.$destroy();
innerScope = scope.$new();
if (mode == 'VIEW') {
element.empty().append(viewFn(innerScope));
} else {
element.empty().append(editFn(innerScope));
}
});
};
}
};
}]);
它工作正常,除非模板包含一个不是根元素的Ng-repeat,在这种情况下它表现得很奇怪:
要重现,请转到http://plnkr.co/edit/RCqlNWTVdXVoMQCkFcQn?p=preview 并从编辑到视图切换一些时间。
您会注意到ng-repeat的迭代次数会随着时间的推移而增长。 第一次,它显示123和456,就像它应该
在第一次来回查看和编辑之后,它显示123123和456456
每次在视图和编辑之间来回切换时,它都会不断添加一次迭代。
答案 0 :(得分:1)
我可能在发布后不久就找到了解决方案。
问题显然在于ng-repeat需要克隆模板。
在角度源中发表评论后,我们可以将第二个参数传递给compile返回的函数。
第二个参数是一个函数,它通过模板的克隆(以及链接到的范围)来调用。
所以而不是
if (mode == 'VIEW') {
element.empty().append(viewFn(innerScope));
} else {
element.empty().append(editFn(innerScope));
}
我能做到
function setElts(elts) {
element.empty().append(elts);
}
if (mode == 'VIEW') {
viewFn(innerScope, setElts);
} else {
editFn(innerScope, setElts);
}
答案 1 :(得分:1)
也许你可以做this。
首先,您在视图中直接注入新的dom。之后,抓住它并应用$ compile。
像这样;var viewFn = "<div>View: <span ng-repeat='x in [1,2,3]'>{{x}}</span></div>";
...
element.html(viewFn);
...
$compile(tElement.contents())(innerScope);