Reputation: 4679
I'm using ng-boilerplate and have to add the possibility to use different templates in production, based on the user configuration.
.config(function config( $stateProvider ) {
$stateProvider.state( 'demo', {
url: '/demo',
views: {
"main": {
controller: 'DemoCtrl',
templateUrl: 'demo/demo.tpl.html'
}
}
});
})
My current idea is to make the templateUrl dynamic
templateUrl: 'demo/demo'+userService.getTemplate()+'.tpl.html'
and having multiple template files, like:
while the userService function does provide the template version to use, e.g. ".b"
Do you agree? Is there maybe a better/easier approach to this problem?
Upvotes: 13
Views: 5683
Reputation: 2316
I've a different way based on the same principle
Except you don't have to actually request the view yourself with $http.
So you can let ui-router handle that part.
Which is easier when you have a complex view architecture.
.state('public.index', {
url: '/',
views: {
"": {
template: '<div ui-view="abTestDummyView"></div>',
controller: ['landing', '$http', function(landing, $http) {
alert('Showing AB Test Landing #' + landing);
// increment landing stats
$http.get('http://stats.domain.com', {landing: landing});
}],
controllerAs: 'landingCtrl',
},
"[email protected]": {
templateProvider: ['landing', function(landing) {
// inject a view based on its name
return "<div ui-view=\"ab" + landing + "\"></div>";
}]
},
"[email protected]": {
template: "INJECTED AB1"
// replace by templateUrl: "/real path/"
},
"[email protected]": {
template: "INJECTED AB2"
// replace by templateUrl: "/real path/"
}
},
resolve: {
landing: function() {
return Math.floor((Math.random() * 2) + 1);
}
}
})
Upvotes: 0
Reputation: 8222
I will not keep it in service, because service will be a part of js file. Which will be static (under normal condition)
This is how I will do it, In html
file I will put
window.abConfig = "defaultVersion";
In app.js I will put
.config(function config( $stateProvider ) {
$stateProvider.state( 'demo', {
url: '/demo',
views: {
"main": {
controller: 'DemoCtrl',
templateUrl: function() {
return 'demo/demo' + window.abConfig + '.tpl.html';
}
}
}
});
})
Its kind of Hacky way, but it gives me flexibility to decide which version to display to user at server level. I might require to write logic before user download the content based on user's previous activity, which I can not do from client side javascript.
Upvotes: 2
Reputation: 292
This can be achieved using standard angular, you just have to look at it from another angle!
I would suggest using the $templateCache. When you load the app you can pre-populate the $template cache with the selected version of the user templates.
You can do something like
$templateCache.put("page-header.html", '<h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>');
Also if your not opposed to the idea, you can place the templates into the page using the script tag syntax, where the id == the templateURL you use in your $routeProvider.
<script type="text/ng-template" id="page-header.html">
<h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>
</script>
And ng will load it directly from the script tag.
Upvotes: 1
Reputation: 19922
AngularJS standard $routeProvider
can accept function for templateUrl. But you can't inject services into this function.
ui-router
has templateProvider
parameter into which you can inject what you want and you should return something like this for remote template case:
$stateProvider.state('demo', {
templateProvider: function ($http, $templateCache, $stateParams, userService) {
var url = 'demo/demo' + userService.getTemplate() + '.tpl.html';
return $http.get(url, { cache: $templateCache }).then(function (response) {
return response.data;
});
}
})
Upvotes: 11