I'm trying to pass in the url for the template via a scope variable. The scope will not change so the template doesn't need to update based on it, but currently the scope variable is always undefined.
<div cell-item template="{{col.CellTemplate}}"></div>
Ideally the directive would be:
.directive("cellItem", ["$compile", '$http', '$templateCache', '$parse', function ($compile, $http, $templateCache, $parse) {
return {
scope: {
template: '@template'
},
templateUrl: template // or {{template}} - either way
};
}])
This doesn't work however. I've tried a lot of different permutations in accomplishing the same concept, and this seems the closest, however it still doesn't work.
.directive("cellItem", ["$compile", '$http', '$templateCache', '$parse', function ($compile, $http, $templateCache, $parse) {
return {
scope: {
template: '@template'
},
link: function (scope, element, attrs) {
var templateUrl = $parse(attrs.template)(scope);
$http.get(templateUrl, { cache: $templateCache }).success(function (tplContent) {
element.replaceWith($compile(tplContent)(scope));
});
}
};
}])
I've also tried using ng-include, but that also doesn't evaluate scope variables before compiling. The CellTemplate value is coming from a database call so is completely unknown before evaluation. Any suggestions for getting this working would be greatly appreciated!
Edit: I'm using angular 1.0.8 and am not able to upgrade to a newer version.
You are not far off at all.
You don't need to use an isolated scope for the directive. You can pass the templateUrl like this:
<div cell-item template="col.CellTemplate"></div>
Then add a watch to detect when the template value changes:
.directive("cellItem", ["$compile", '$http', '$templateCache', '$parse', function ($compile, $http, $templateCache, $parse) {
return {
restrict: 'A',
link: function(scope , element, attrs) {
scope.$watch(attrs.template, function (value) {
if (value) {
loadTemplate(value);
}
});
function loadTemplate(template) {
$http.get(template, { cache: $templateCache })
.success(function(templateContent) {
element.replaceWith($compile(templateContent)(scope));
});
}
}
}
}]);
Here is a working Plunker: http://plnkr.co/edit/n20Sxq?p=preview
If you don't want to deal with the linking logic yourself, or you want the isolate scope, I think this is simpler:
.directive("cellItem", ["$compile", '$http', '$templateCache', '$parse', function ($compile, $http, $templateCache, $parse) {
return {
scope: {
template: '@template'
},
template: "<div ng-include='template'></div>"
};
}])
or:
template:"<ng-include src='template'></ng-include>"
It's an old post but I thought its useful if anyone lands in here for the answer.
You can try the templateUrl function as @caub mentioned in a comment. Same can also be used for components.
.directive("cellItem", ["$compile", '$http', '$templateCache', '$parse', function ($compile, $http, $templateCache, $parse) {
return {
templateUrl: function(element, attrs) {
return attrs.template || 'someDefaultFallback.html';
}
};
}]);
We don't need any of the injected dependencies here. Hope this helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With