I have a custom directive that simply $compiles a template into another.
.directive('staticInclude', function($http, $templateCache, $compile) {
return function(scope, element, attrs) {
var templatePath = attrs.staticInclude;
//
$http.get(templatePath, {
cache: $templateCache
}).success(function(response) {
var contents = element.html(response).contents();
$compile(contents)(scope);
});
};
});
I use it like:
<div static-include="components/campaign/details.html"></div>
Because I'm using aliases for the controller (using angular UI router), all model in any of the templates are like:
<p>Delivery Time: <span class="text-medium">{{CtrlAlias.campaign.newsletter.sentDate | date:CtrlAlias.currentUser.params.settings}}</span></p>
How do I make this directive work in multiple templates where CtrlAlias changes?
I tried changing $compile(contents)(scope); into $compile(contents)(scope.newCtrlAlias);
Any ideas?
When you $compile and then link, you are free to provide your own scope against which the compiled content is linked. That means that you can have the template content refer to some arbitrary ViewModel name, say vm
:
<p>Delivery Time: <span>{{vm.campaign.newsletter.sentDate}}</span></p>
And link against a scope that has vm
property:
var scope = { vm: {...} }
It actually might be even useful to use an isolate scope for your compiled content, to make sure that you aren't assuming an existence of scope variables that may or may not be there when the content is linked:
.directive('staticInclude', function($templateRequest, $compile) {
return {
link: function(scope, element, attrs){
var alias = attrs.alias || 'vm';
var templatePath = attrs.staticInclude;
var newScope = scope.$new(true); // isolate scope
newScope.vm = scope[alias];
// $templateRequest is essentially $http with $templateCache
$templateRequest(templatePath)
.then(function(html){
$compile(html)(newScope, function cloneAttachFn(clone){
element.empty();
element.append(clone);
});
});
}
};
});
Then usage is like so:
<div ng-controller="MainCtrl as main">
<div static-include="components/campaign/details.html" alias="main">
</div>
</div>
Really not sure I understand why you would need to use this so it's not easy to answer. However, one possible solution could be to wrap the template in a <div>
to which you can append the desired controller information. It's a bit gross but it might work for you. You would have to pass in the controller name and it's alias but you could perhaps add that to your $state
's data properties and access them from that but again it all seems a bit hacky.
DEMO
app.directive('staticInclude', function($http, $templateCache, $compile) {
return {
scope: {
ctrlName : '@',
alias : '@'
},
link: link
};
function link(scope, element, attrs) {
var templatePath = attrs.staticInclude;
$http
.get(templatePath, {
cache: $templateCache
})
.success(function(response) {
var ctrlStr = scope.ctrlName + ' as ' + scope.alias,
template = '<div ng-controller="' + ctrlStr + '" >' + response + '</div>',
contents = element.html(template).contents();
$compile(contents)(scope);
});
};
});