Beware
The decision made will break the directive with replace: true : HTML will not be replaced, the special CSS selector will no longer work, etc.
I want my directive to dynamically change its template, observing the string received as an attribute from the parent controller, so I used $compile from this answer along with $observe from this small part of an interesting tutorial , but alas, it does not work as shown in this plunkr .
About error
If jQuery is enabled before AngularJS in scripts, calling replaceWith causes me the following error:
TypeError: Cannot read property 'ownerDocument' of undefined
But , if I remove jQuery, forcing AngularJS to use its jqLite, the same part generates this error, making things clearer for a general jQuery agnostic like me:
TypeError: Failed to execute 'replaceChild' on 'Node': parameter 1 is not of type 'Node'.
Even if it is clear to me that I am not passing a valid Node-type object to replaceWith , I donβt know how to handle this situation, as I expected $compile to do the job.
The only thing I know is what console.log(tplContent) looks like console.log(tplContent) I right 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" }
while console.log($compile(tplContent)(scope)) returns an array with the same object as the first and only element:
[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
I really want to avoid using one of the following two backups, do you have any idea what I'm doing wrong here?
Failures aka don't tell me about it
I know that I could split the directive into two directives and ng-if them as follows:
(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() {} })()
and then in 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>
I also know that I can use 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'; } } })()