Trying to Dynamically set a templateUrl in controller based on constant

ghz 1years ago ⋅ 4638 views

Question

I want to change the templateUrl associated with controller based on a preset constant that I've defined in my angularjs bootstrap. I can't figure out how to change that. I've experimented with UrlRouteProvider but have not been able to figure out how to pull the html in from the file system with that. I'm stuck on templateUrl.

In the below code, the output first shows that "svcc is indeed passed into the first function's console.out but in the templateUrl definition function, CONFIG is undefined.

I'm open to other ways to do this.

    var app = angular.module('svccApp', [
        'ui.router'
    ]);

    var myConstant = {};
    myConstant.codeCampType = "svcc";
    app.constant("CONFIG", myConstant);

    app.config(['$stateProvider', '$urlRouterProvider','CONFIG',
        function ($stateProvider, $urlRouterProvider,CONFIG) {
            console.log(CONFIG.codeCampType);
            $stateProvider
                .state('home', {
                    url: '/home',
                    //templateUrl: 'index5templateA.html',   (THIS WORKS)
                    templateUrl: function(CONFIG) {
                        console.log('in templateUrl ' + CONFIG.codeCampType);
                        if (CONFIG.codeCampType === "svcc") {
                            return 'index5templateA.html';
                        } else {
                            return 'index5templateB.html';
                        }
                    },
                    controller: function ($state) {
                    }
                });
        }]);

Answer

I created a plunker here You are almost there, just the syntax is 'templateProvider' :

.state('home', {
    url: '/home',
    //templateUrl: 'index5templateA.html',   (THIS WORKS)
    // templateUrl: function(CONFIG) {
    templateProvider: function(CONFIG) {
    ...

Snippet from doc:

Templates

TemplateUrl
... templateUrl can also be a function that returns a url. It takes one preset parameter,stateParams, which is NOT injected.

TemplateProvider
Or you can use a template provider function which can be injected, has access to locals , and must return template HTML, like this:

So in our case, that would be the implementation:

 $stateProvider
    .state('home', {
        url: '/home',
        //templateUrl: 'index5templateA.html',   (THIS WORKS)
        templateProvider: function(CONFIG, $http, $templateCache) {
            console.log('in templateUrl ' + CONFIG.codeCampType);
            
            var templateName = 'index5templateB.html';
            
            if (CONFIG.codeCampType === "svcc") {
                 templateName = 'index5templateA.html';
            } 
            var tpl = $templateCache.get(templateName);
            
            if(tpl){
              return tpl;
            }
            
            return $http
               .get(templateName)
               .then(function(response){
                  tpl = response.data
                  $templateCache.put(templateName, tpl);
                  return tpl;
              });
        },
        controller: function ($state) {
        }
    });

Check the examle here

Also check: