小心
接受的解决方案将破坏带有 replace: true
的指令:HTML 将不会被替换,正在使用的特定 CSS 选择器将不再起作用,等等。
我希望我的指令通过观察从父 Controller 作为属性接收的字符串来动态更改其模板,因此我使用了 this answer 中的 $compile
与 this small part of an interesting tutorial 中的 $observe
一起使用,但是唉它不起作用,如this plunkr所示.
关于错误
如果脚本中 AngularJS 之前包含 jQuery,则 replaceWith
调用会抛出以下错误:
TypeError: Cannot read property 'ownerDocument' of undefined
但是如果我删除 jQuery,强制 AngularJS 使用它的 jqLite,同一部分会抛出此错误,让像我这样完全不了解 jQuery 的人变得更清楚:
TypeError: Failed to execute 'replaceChild' on 'Node': parameter 1 is not of type 'Node'.
即使我很清楚我没有将有效的“Node”类型对象传递给 replaceWith
,我也不知道如何处理这种情况,因为我期待 $compile
来完成这项工作。
我唯一知道的是 console.log(tplContent)
看起来像这样(我的 promise 是对的吗?):
Object
{
config: Object
data: "<script type="text/ng-template" id="templateId.html">
↵ <p>TEMPLATE A</p>
↵</script>"
headers: function (d)
ng339: 10
status: 200
statusText: "OK"
}
而 console.log($compile(tplContent)(scope))
返回一个数组,该数组与第一个也是唯一一个项目具有相同的对象:
[Object]
0: {
config: Object
data: "<script type="text/ng-template" id="templateId.html">
↵ <p>TEMPLATE A</p>
↵</script>"
headers: function (d)
ng339: 10
status: 200
statusText: "OK"
},
length: 1
我确实想避免使用以下两个后备方案中的任何一个,您知道我在这里做错了什么吗?
<小时/>后备又名不告诉我这样做
我知道我可以将指令拆分为两个指令,然后 ng-if
它们如下所示:
(function() {
'use-strict';
angular.module('app')
.directive('dynamicTemplateA', dynamicTemplate);
DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];
function dynamicTemplate($http, $templateCache, $compile, $parse) {
var directive = {
restrict: 'E',
templateUrl: 'template-a.html',
scope: {},
bindToController: {
tpl: '@',
i: '='
},
controller: DynTplCtrl,
controllerAs: 'dyntplctrl',
link: linkFunc
}
return directive;
function linkFunc(scope, el, attrs, ctrl) {}
}
DynTplCtrl.$inject = [];
function DynTplCtrl() {}
})()
(function() {
'use-strict';
angular.module('app')
.directive('dynamicTemplateB', dynamicTemplate);
DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];
function dynamicTemplate($http, $templateCache, $compile, $parse) {
var directive = {
restrict: 'E',
templateUrl: 'template-b.html',
scope: {},
bindToController: {
tpl: '@',
i: '='
},
controller: DynTplCtrl,
controllerAs: 'dyntplctrl',
link: linkFunc
}
return directive;
function linkFunc(scope, el, attrs, ctrl) {}
}
DynTplCtrl.$inject = [];
function DynTplCtrl() {}
})()
然后在controller.html
中:
<div ng-repeat="i in [1,2,3]">
<dynamic-template-a ng-if="mainctrl.tpl === 'a'" tpl="{{mainctrl.tpl}}" i="i"></dynamic-template-a>
<dynamic-template-b ng-if="mainctrl.tpl === 'b'" tpl="{{mainctrl.tpl}}" i="i"></dynamic-template-b>
</div>
我也知道我可以使用ng-include
like this :
(function() {
'use-strict';
angular.module('app')
.directive('dynamicTemplateA', dynamicTemplate);
DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];
function dynamicTemplate($http, $templateCache, $compile, $parse) {
var directive = {
restrict: 'E',
template: '<div ng-include="dyntplctrl.getTemplateUrl()"></div>',
scope: {},
bindToController: {
tpl: '@',
i: '='
},
controller: DynTplCtrl,
controllerAs: 'dyntplctrl',
link: linkFunc
}
return directive;
function linkFunc(scope, el, attrs, ctrl) {}
}
DynTplCtrl.$inject = [];
function DynTplCtrl() {
var vm = this;
vm.getTemplateUrl = _getTemplateUrl;
function _getTemplateUrl() {
return 'template-' + vm.tpl + '.html';
}
}
})()
最佳答案
感谢 this question 。
在替换模板时,您需要稍微更改一下代码:
el.html(tplContent.data);
$compile(el.contents())(scope);
这将替换元素的内容(尽管您需要在此处处理清理),然后在指令的范围内编译模板。
此外,为了进行测试,我删除了 <script>
来自 template-a.html
的标签,和template-b.html
.
这是一个forked plunker其中有上述更改。
关于jquery - AngularJS - 无法在链接函数中动态更改指令模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43234325/