How to pass templateUrl via scope variable in attribute

I am trying to pass the url of a template using a scope variable. The volume will not change, so the template does not need to be updated based on it, but at present 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 }; }]) 

However, this does not work. I tried many different permutations while doing 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 also tried using ng-include, but this also does not evaluate scope variables before compilation. The value of the CellTemplate comes from a database call, so it is completely unknown before evaluation. Any suggestions for getting this work would be greatly appreciated!

Edit: I am using angular 1.0.8 and cannot upgrade to a newer version.

+8
angularjs
source share
3 answers

You are just around the corner.

You do not need to use an isolated scope for this directive. You can pass templateUrl as follows:

 <div cell-item template="col.CellTemplate"></div> 

Then add a clock to determine when the pattern 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

+14
source share

If you do not want to deal with the binding logic yourself or want a selection area, 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>" 
+6
source share

This is an old post, but I thought it was useful if someone landed here for an answer.

You can try the templateUrl function like @caub mentioned in the comment. The same can 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'; } }; }]); 

Here we do not need any nested dependencies. Hope this helps someone.

+1
source share

All Articles