6

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) {
                    }
                });
        }]);
Peter Kellner
  • 14,748
  • 25
  • 102
  • 188

3 Answers3

7

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:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thanks Radim. I did see both of those posts but I feel like I'm not so close. Getting the templates with $http and caching them really confuses me. I think I'm almost there if I would return a template and not templateUrl. I feel like if $templateFactory.fromUrl worked I'd be there but that provider seems to no longer exist. – Peter Kellner Jan 05 '15 at 06:26
  • In so much hurry... sorry... I created the plunker, and that should show how to handle caching and $http and... please check the latest link ... please – Radim Köhler Jan 05 '15 at 06:52
  • Thanks Radim. Is the function necessary that you set $rootScope in? Your solution is elegant. Thanks so much, what I was hoping for. – Peter Kellner Jan 05 '15 at 07:07
  • No no ;) ;) I usually do have some start up scritps in my toolbelt... to create plunker ASAP. ;) that's just... Enjoy mighty UI-Router – Radim Köhler Jan 05 '15 at 07:08
3

I have to add another answer, related to brand new feature of angular 1.3

$templateRequest

The $templateRequest service downloads the provided template using $http and, upon success, stores the contents inside of $templateCache.

Usage

$templateRequest(tpl, [ignoreRequestError]);

Arguments - tpl string - The HTTP request template URL

  • ignoreRequestError (optional) boolean - Whether or not to ignore the exception when the request fails or the template is empty

And updated plunker

templateProvider: function(CONFIG, $templateRequest) {
    console.log('in templateUrl ' + CONFIG.codeCampType);

    var templateName = 'index5templateB.html';

    if (CONFIG.codeCampType === "svcc") {
         templateName = 'index5templateA.html';
    } 

    return $templateRequest(templateName);
},
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
2
 var app = angular.module('svccApp', [
        'ui.router'
    ]);

    var myConstant = {};
    myConstant.codeCampType = "svcc";

    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() {
                        if (myConstant.codeCampType === "svcc") {
                            return 'index5templateA.html';
                        } else {
                            return 'index5templateB.html';
                        }
                    },
                    controller: function ($state) {
                    }
                });
        }]);
dhavalcengg
  • 4,678
  • 1
  • 17
  • 25
  • when I test this, I don't appear to have access to myConstant in the function – Peter Kellner Jan 05 '15 at 07:07
  • you will. app.config will have closure of myConstant. You are creating your myConstant as global variable. When your templateUrl function will execute you will have your myConstant. – dhavalcengg Jan 05 '15 at 07:15
  • You are clearly right when i run it but i'm confused. In my example it seems not to be global but in your example it does. What I not understanding? -thanks – Peter Kellner Jan 05 '15 at 17:42
  • please ignore my last comment. I get it now. http://stackoverflow.com/questions/4862193/javascript-global-variables – Peter Kellner Jan 05 '15 at 17:50