接受的解决方案将破坏replace: true
的指令:HTML不会被替换,正在使用的特定CSS选择器将不再起作用等。
我希望我的指令通过观察从父控制器接收的字符串来动态更改其模板,因此我使用this answer中的$compile
和来自{{3}的$observe
},但唉它不起作用,如this small part of an interesting tutorial所示。
如果脚本中的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)
看起来像这样(我承诺是对的吗?):
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
this plunkr:
(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';
}
}
})()
答案 0 :(得分:2)
您需要在替换模板时稍微更改一下代码:
el.html(tplContent.data);
$compile(el.contents())(scope);
这将替换元素的内容(虽然你需要在这里处理清理),然后在指令的范围内编译模板。
此外,为了进行测试,我删除了<script>
和template-a.html
中的template-b.html
代码。
以下是forked plunker,其中包含上述更改。
答案 1 :(得分:0)
您不必将HTML
放在脚本标记中。只需将纯HTML存储在文件中,如
模板a.html
<p>TEMPLATE A</p>
稍微修改你的代码以达到你想要的效果。
function(tplContent) {
var content = $compile(tplContent.data)(scope);
if(el[0].childNodes.length){
el[0].removeChild(el[0].childNodes[0]);
}
el.append(content);
}