9

this is my app.js file- i have one parent state and two child states. Both the child views need the object.

    states.push({
      name: 'parentstate',
      url: '/parent/:objId',
      abstract: true,
      templateUrl: 'views/parentview.html',
      controller: function() {},
      resolve: {
        obj: function(OBJ, $stateParams) {
          return OBJ.get($stateParams.objId);
        }
      }
    });

i want to use this resolved obj to decide child template

    states.push({
      name: 'parentstate.childs',
      url: '/edit',
      views: {
        "view1@parentstate": {
          templateUrl: 'views/view1',
          controller: 'view1Ctrl'
        },
        "view2@parentstate": {
          templateUrl: function(obj) {
            if (obj.something == something) {
              return "views/view2first.html";
           } else {
              return 'views/view2second.html';
            }
          },
          controller: 'view2Ctrl'
        }
      }  
    });

How can i achieve this?

vaibhavkhl
  • 93
  • 1
  • 6

1 Answers1

8

There is a working example. Instead of templateUrl we should use the templateProvider. This is new state def:

  $stateProvider
    .state('parentstate.childs', {
      url: '/edit',
      views: {
        "view1@parentstate": {
          templateUrl: 'views.view1.html',
          controller: 'view1Ctrl',
        },
        "view2@parentstate": {
          templateProvider: function($http, $stateParams, OBJ) {

            var obj = OBJ.get($stateParams.objId);
            var templateName = obj.id == 1
              ? "views.view2.html"
              : "views.view2.second.html"
              ;
        
            return $http
                  .get(templateName)
                  .then(function(tpl){
                    return tpl.data;
                  });
          },
          controller: 'view2Ctrl',
        }
      }
    });

Why are we using this approach? as documented here:

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:

Check the TemplateProvider based solution in this working plunker

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • But i want to use that obj in view1Ctrl too. And i dont want to make two api calls. – vaibhavkhl Aug 13 '14 at 15:55
  • I showed you, how powerful `ui-router` is. Also, I tried to explain to you how the Templating is designed, and what we can achieve with `TemplateUrl` and what with `TemplateProvider`. Now its up to you how to solve the reuse of the *boj*. I would vote for caching... but that is not the `ui-router` responsibility... BTW In my experience, I never needed to drive template selection by some params. Just drive the state and its template... inside of the template use `directives` to render the content based on the content... Does it help? – Radim Köhler Aug 13 '14 at 15:59
  • yeah it definitely helps. As you said you never needed to decide template on basis of some params. I think my approach is wrong and i should think again. I will see how i can use directives for this case. Thank you. – vaibhavkhl Aug 13 '14 at 16:08
  • Great if that helped anyhow. I am using ui-router and cannot imagine world without that. Just our thinking must be a bit chnaged ;) You will be able to upvote, once you get reputation 15 (or more)... but you can accept! if the asnwer helps and get some score as well ;) good luck with `ui-router` – Radim Köhler Aug 13 '14 at 16:14