2

I'm trying to load a template file using a rootscope value as for it's name. I have a init controller which sets the $rootScope.template to "whatever.html", then I have my route like this:

$stateProvider.state('/', {
  url: '/',
  access: 'public',
  views: {
    page: {
      controller: 'HomeCtrl',
      templateProvider: function($templateFactory, $rootScope) {
        return $templateFactory.fromUrl('/templates/' + $rootScope.template);
      }
    }
  }
});

But this doesn't work. It actually freezes the whole chrome so that I have to kill the process in order to stop it... I've also tried this with templateUrl but with no results.

So how could I use my dynamic template file with UI-router?

QlliOlli
  • 637
  • 3
  • 13
  • 25
  • could you create a plunkr.co to show this failing in context? – stukennedy Nov 11 '14 at 11:53
  • 1
    templateProviders seems okay. I created a plunker for this: http://plnkr.co/edit/x8tsIBkKHM1cxfstyESt?p=preview So, problem is probably not here. – halilb Nov 11 '14 at 12:23
  • Yes, seems to work ok. My problem was/is that this $rootscope value is a query value from a database. Now everything works ok if I declare the $rootScope.template manually but the query takes too long (or I don't really know what the problem is) and is therefore not ready by the time templateProvider would need it. – QlliOlli Nov 11 '14 at 14:04
  • Any ideas how to fetch my template name and use that in my router? Like the question above but instead of $rootScope.template = "whatever.html" it would be a query value? – QlliOlli Nov 11 '14 at 14:13

1 Answers1

4

Similiar to your other question (in order I found them): Angular and UI-Router, how to set a dynamic templateUrl, I also created a working plunker to show how to. How it would work?

So, if this would be state call:

<a href="#/parent/child/1">#/parent/child/1</a>
<a href="#/parent/child/2">#/parent/child/2</a>

And these would be states:

  $stateProvider
    .state('parent', {
      url: '/parent',
      //abstract: true,
      templateUrl: 'views.parentview.html',
      controller: function($scope) {},
    });

  $stateProvider
    .state('parent.child', {
      url: '/child/:someSwitch',
      views: {
         // see more below

Then we can use this templateProvider definiton:

templateProvider: function($http, $stateParams, GetName) {

    // async service to get template name from DB
    return GetName
        .get($stateParams.someSwitch)
        // now we have a name
        .then(function(obj){
           return $http
              // let's ask for a template
              .get(obj.templateName)
              .then(function(tpl){
                  // haleluja... return template
                  return tpl.data;
           });      
        })

}, 

What we can see is chaining of async results:

// first return of promise
return asyncstuff
  .then(function(x){
    // second return of a promise once done first
    return asyncstuff
      .then(function(y){  
       // again  
        return asyncstuff
          .then(function(z){
            return ... it
          }
      }

  }

And that's what the magical templateProvider can do for us... wait until all promises are resolved and continue execution with known template name and even its content. Check the example here. More about template provider: Angular UI Router: decide child state template on the basis of parent resolved object

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • This looks promising, but I gotta ask, is the $http service really necessary to get a template? (This is what I understood from looking at your plunker example), the factory GetName#get does return the template name already, so... is the $http call on line 29 of your plunker necessary for all this to work? and why? Thanks! – jlstr Oct 29 '15 at 15:33
  • @Jose in case I do understand your question, I would rather use $templateRequest discussed e.g. [here](http://stackoverflow.com/a/28872022/1679310) or [there](http://stackoverflow.com/a/30409867/1679310) – Radim Köhler Oct 29 '15 at 15:43
  • Cool, looking at your suggestion now. However, for argument's sake, do you think you could answer my question? Does templateProvider indeed requires a *final* call to $http to get a template? Thank you for your kind reply. – jlstr Oct 29 '15 at 15:52
  • 1
    @Jose, sorry do not have so much time.. but I guess yes. GetName just gets the name, while $http get the content of it. templateProvider must return the template! so, it must call $http to get it. Hope it helps a bit.. maybe issue fresh question, and large audience could give you even better direction.. – Radim Köhler Oct 29 '15 at 15:56
  • That's ok! this was good enough for now. We programmers are always busy! your suggestion looks even better. Reading up! Have a nice day. – jlstr Oct 29 '15 at 15:58