Search code examples
angularjsviewnestedangular-ui-routerstates

Angular and ui-router - How to configure nested state within named view in parent state


I am building a webapp that contains some elements that appear on every "page" and one area where the content changes according to which "page" is navigated to. To achieve this,, I'm using ui-router with multiple named views and nested states. My problem comes when I try to nest a state in one of the named views of its parent. I'm thinking I'm not targeting the named view in the parent correctly because nothing in the nested state is displayed.

    $stateProvider
        .state('stc', {
            abstract: true,
            url: '/',
            views: {
                'shell': {
                     template: '<div ui-view="topbar"></div>' +
                               '<div ui-view="navbar"></div>' +
                               '<div ui-view="content"></div>'
                }
            }
        })
        .state('stc.sections', {
            url: '',
            views: {
                'topbar@stc': {
                    template: "<p>top bar</p>"
                },
                'navbar@stc': {
                    template: "<p>nav bar</p>"
                },
                'content@stc': {
                    template: '<div ui-view></div>'
                }
            }
        })
        .state('stc.sections.homepage', {
            url: '/',
            template: '<h1>Nested Home Page Content</h1>'
        });

I'm can't figure out how to target the parent's named view: content@stc so that i can nest dynamic content based on the url. In this case, I'm trying to load home page content.

Is there some special notation required to target a named view?


Solution

  • I ended up removing the line: url: '' from the stc.sections configuration and replaced url: '/' with url: '' in the `state.sections.homepage config. I'm now able to add routes for sibling pages using something like:

            .state('stc.sections.login', {
                url: 'login',
                controller: 'main.common.login as loginCtrl',
                template: require('./views/login.html')
            })
    

    and access them in a browser with URLs like

    • mydomain.com/
    • mydomain.com/login
    • mydomain.com/signup
    • etc

    Modified Code

    $stateProvider
        .state('stc', {
            abstract: true,
            url: '/',
            views: {
                'shell': {
                     template: '<div ui-view="topbar"></div>' +
                               '<div ui-view="navbar"></div>' +
                               '<div ui-view="content"></div>'
                }
            }
        })
        .state('stc.sections', {
            views: {
                'topbar@stc': {
                    template: "<p>top bar</p>"
                },
                'navbar@stc': {
                    template: "<p>nav bar</p>"
                },
                'content@stc': {
                    template: '<div ui-view></div>'
                }
            }
        })
        .state('stc.sections.homepage', {
            url: '',
            template: '<h1>Nested Home Page Content</h1>'
        })
        .state('stc.sections.login', {
            url: 'login',
            template: '<h1>Login Here</h1>'
        })