Can you change templateUrl on the fly?
Is it possible to change templateUrl on the fly by passing values in the directive's scope? I want to pass data to controller that will render the page based on the data that passed from the directive
something maybe that looks like that:
<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.
}
});
It is possible, but when your template to be loaded depends on some scope-data you can't use the directive's templateUrl
property anymore and you will be obliged to use lower-level API, namely $http
and $compile
.
Roughly what you need to do (only possible in the linking function) is to retrieve template's content using $http
(don't forget to involve $templateCache
!) and then compile template's content "manually".
It might sound like it is a lot of work but in practice it is rather straightforward. I would suggest having a look at the ngInclude
directive sources where this pattern is used.
Here is a 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 that it would be used as <boom data='name'></boom>
. Working plunk here: http://plnkr.co/edit/TunwvhPPS6MdiJxpNBg8?p=preview
Please note that I've changed attributes evaluation from {{name}}
to attributes parsing since probably a template should be determined only once, at the beginning.
This is a new feature in Angular versions 1.1.4+ I just found out if I use the current unstable (1.1.5) you can pass a function into the template url of a directive. The second parameter of the function is the value of the attribute directive as shown below.
Here is a link to the unpublished docs showing the official change.
To use partials/template1.html
as the template url 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"
])
I had 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>