7

If I have index.html with:

<body> <ui-view="home"></home> </body>

Then inside that home view i render frame.html with the following inside:

<div ui-view="home_content"></div>

In my app.js I've been trying to get the most inner the ui-view inside frame.html to render another html template. I'm able to render the content in the home view just fine but nothing renders inside home_content.

My app.js ui-router code

    $stateProvider
        .state('user', {
            abstract: true,
            template: '<ui-view/>',
            data: {
                access: AccessLevels.user
            }
        })

        .state('user.home', {
            url: '/home',
            views: {
                'home@': {
                    templateUrl: 'app/partials/home/frame.html',
                    controller: 'homeCtrl'
                },
                'home_content@home': {
                    templateUrl: 'app/partials/home/dashboard/index.html',
                    controller: 'dashboardCtrl'
                }
            }
        });

Seems like I may be coming at this all wrong, not sure if the above is the right way to go about it.

Dayan
  • 7,634
  • 11
  • 49
  • 76

3 Answers3

2

There is a working plunker

I would expect, that you want to target unnamed view of your parent in the child, so the view should be defined like this:

$stateProvider
    // here we define parent
    .state('user', {
        abstract: true,
        // parent has UNNAMED view
        template: '<ui-view/>', // this will be injected into index.html
        ...                     // ui-view=""
    })
    // child will partilly target parent
    // and also itself
    .state('user.home', {
        url: '/home',
        views: {
            // here we target parent UNNAMED view
            '': {
                ...
            },
            // here we target current state
            // so we should use state name
            'home_content@user.home': {
                ...
            }
        }
    });

What would also work is instead of '' : { } we can use '@home' : {} (see the doc below).

In case (as mentioned below in the comment) we have index.html with target named home:

<div ui-view="home"></div>

We can use this plunker, which redefines the parent abstract state like this:

$stateProvider
    .state('user', {
        abstract: true,
        data: {
            ...
        },
        views : {
          'home' : {
            template: '<div ui-view=""></div>',
          }
        }
    })

Check the doc

View Names - Relative vs. Absolute Names

Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname@statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.

For example, the previous example could also be written as:

.state('report',{
    views: {
      'filters@': { },
      'tabledata@': { },
      'graph@': { }
    }
})
Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • I'm now getting blank page, no console errors and network tab shows both templates in the GET request, but the browser ends up displaying just a blank page.. I'm trying to get index.html which has `ui-view` called "home" to render a template with some html and a container which has ui-view called `home_content`. Home content will point to various templates that will be rendered depending on the menu items selected. If i check out the source, its simply the index.html with the `ui-view="home"` – Dayan Apr 09 '15 at 17:22
  • Here is a working plunker http://plnkr.co/edit/ABAY3AfoNSfZSH8o0ybD?p=preview. It should show all above in action. Well this plunker is related to my expectations... I will also show you solution with your details mentioned in the comment... another plunker with home in index.html added to answer: http://plnkr.co/edit/seYHd0CTRnmeTEmMVo9N?p=preview – Radim Köhler Apr 09 '15 at 17:39
  • Thank you for this, I finally got it working. Quick question, I noticed you used `ui-sref` to link to another state? Is this prefer over href? I was doing stuff like `#/home`. Thanks! – Dayan Apr 09 '15 at 18:07
  • I would put it this way. The `ui-sref` is here as an API. We can have stable states and navigation ala `ui-sref="myState.Child({paramKey: paramValue})"` while the `url` defined could change. Also, we can start to think more in states, rather then in url. At the end, we can even have state which does not have url defined at all. Maybe check an example here http://stackoverflow.com/a/25591908/1679310 and about ui-sref and params sending here http://stackoverflow.com/q/25647454/1679310 – Radim Köhler Apr 09 '15 at 18:49
  • Thank you, that clears that up! Also, if i wanted to switch between multiple views inside one state, I noticed that ui-sref didnt work - Error: Could not resolve 'user.invoice' from state 'user.home'.. I have multiple views, that should load inside that `home_content` placeholder. What would be a good approach for this? – Dayan Apr 09 '15 at 18:57
  • I could, come to you tomorrow... Can you update my plunker to reproduce your issue? ... – Radim Köhler Apr 09 '15 at 19:06
0

Looks like your child .state has wrong code it should be 'home@home_content' instead of 'home_content@home'

    .state('user.home', {
        url: '/home',
        views: {
            '': {
                templateUrl: 'app/partials/home/frame.html',
                controller: 'homeCtrl'
            },
            'home@home_content': {
                templateUrl: 'app/partials/home/dashboard/index.html',
                controller: 'dashboardCtrl'
            }
        }
    });
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
0

You are making your state configuration complex. Just change your code to look like this:

$stateProvider.state('user', {
    abstract : true,
    template : '<ui-view/>',
    data : {
        access : AccessLevels.user
    }
})

.state('user.home', {
    url : '/home',
    views : {
        'home' : {
            templateUrl : 'app/partials/home/frame.html',
            controller : 'homeCtrl'
        },
        'home_content' : {
            templateUrl : 'app/partials/home/dashboard/index.html',
            controller : 'dashboardCtrl'
        }
    }
});

You are actually not using @ properly and which is optional. This should work unless you have your correct view path.

Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121