Can you change templateUrl on the fly?

Is it possible to change templateUrl "on the fly" by passing values ​​in the scope? I want to transfer data to the controller, which will display the page based on the data passed from the directive

something might look like this:

<div> <boom data="{{myData}}" /> </div> .directive('boom', function { return { restrict: 'E', transclude: true, scope: 'isolate', locals: { data: 'bind' }, templateUrl: "myTemplate({{boom}}})" // <- that of course won't work. } }); 
+26
angularjs angularjs-directive
Jan 31 '13 at 18:05
source share
6 answers

Perhaps, but when your download template depends on some area data, you can no longer use the property of the templateUrl directive, and you will be required to use the lower-level API, namely $http and $compile .

Approximately what you need to do (it is possible only in the binding function) is to get the contents of the template using $http (do not forget to include $templateCache !), And then compile the contents of the template manually.

It would seem that this is a lot, but in practice it is quite simple. I would suggest looking at the ngInclude directive sources where this template is used.

Here is the skeleton of such a directive:

 app.directive('boom', function($http, $templateCache, $compile, $parse) { return { restrict: 'E', link: function(scope , iElement, iAttrs) { var boom = $parse(iAttrs.data)(scope); $http.get('myTemplate'+boom, {cache: $templateCache}).success(function(tplContent){ iElement.replaceWith($compile(tplContent)(scope)); }); } } }); 

assuming it will be used as <boom data='name'></boom> . Working snippet here: http://plnkr.co/edit/TunwvhPPS6MdiJxpNBg8?p=preview

Please note that I changed the attribute rating from {{name}} to attribute parsing, since the template should probably be defined only once at the beginning.

+53
Jan 31 '13 at 18:09
source share

This is a new function in versions of Angular version 1.1.4+, which I just recognized, if I use the current unstable (1.1.5), you can pass the function to the url template of the directive. The second parameter of the function is the value of the attribute directive, as shown below.

Here is a link to unpublished documents showing official changes.

To use partials/template1.html as a url template from

Html:

 <div sub_view="template1"></div> 

Directive

 .directive('subView', [()-> restrict: 'A' # this requires at least angular 1.1.4 (currently unstable) templateUrl: (notsurewhatthisis, attr)-> "partials/#{attr.subView}.html" ]) 
+16
Jul 29 '13 at 3:33
source share

I slightly modified the answer from pkozlowski.opensource.

From:

 var boom = $parse(iAttrs.data)(scope); 

To:

 var boom = scope.data.myData 

It worked for me, and it's possible to use

 <boom data="{{myData}}" /> 

in the directive.

+2
Oct 23 '13 at 9:28
source share

I had a similar problem

  return { restrict: 'AE', templateUrl: function(elm,attrs){return (attrs.scrolled='scrolled' ?'parts/scrolledNav.php':'parts/nav.php')}, replace: true, 

 partnersSite.directive('navMenu', function () { return { restrict: 'AE', templateUrl: function(elm,attrs){return (attrs.scrolled='scrolled' ?'parts/scrolledNav.php':'parts/nav.php')}, replace: true, link: function (scope, elm, attrs) { scope.hidden = true; //other logics } }; }); 
 <nav-menu scrolled="scrolled"></nav-menu> 
+2
Jul 23 '15 at 11:11
source share

This is a follow-up answer that addresses some issues with previous answers. It is noteworthy that he will only compile the templates once (which is important if you have a lot of them on your page, and he will follow the changes in the template after binding it. He also copies the class and style from the original element to the template (although not angular does a very elegant way internally when you use β€œreplace: true.” Unlike the current supported method w00> for using a function for a template or Url template, you can use area information to determine the template for the load.

 .directive('boom', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) { //create a cache of compiled templates so we only compile templates a single time. var cache= {}; return { restrict: 'E', scope: { Template: '&template' }, link: function (scope, element, attrs) { //since we are replacing the element, and we may need to do it again, we need //to keep a reference to the element that is currently in the DOM var currentElement = element; var attach = function (template) { if (cache[template]) { //use a cloneAttachFn so that the link function will clone the compiled elment instead of reusing it cache[template](scope, function (e) { //copy class and style e.attr('class', element.attr('class')); e.attr('style', element.attr('style')); //replace the element currently in the DOM currentElement.replaceWith(e); //set e as the element currently in the dom currentElement = e; }); } else { $http.get('/pathtotemplates/' + template + '.html', { cache: $templateCache }).success(function (content) { cache[template] = $compile(content); attach(template); }).error(function (err) { //this is something specific to my implementation that could be customized if (template != 'default') { attach('default'); } //do some generic hard coded template }); } }; scope.$watch("Template()", function (v, o) { if (v != o) { attach(v); } }); scope.$on('$destroy', function(){ currentElement.remove(); }); } }; } ]) 
+1
Dec 30 '15 at 21:41
source share

These answers are good, but not professional. There is a syntax for using templateUrl , which we often do not use. It may be a function that returns a URL . This function has some arguments. If you want more here, this is a cool article.

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html

0
Jul 22 '15 at 16:04
source share



All Articles