1

I have a user layout file that is the template for any user pages:

<div class="user-wrapper">
    <div ui-view="menu"></div>
    <div ui-view="content"></div>
</div>

Depending on the state I want the menu to be different. Such as:

    .state('user', {
        url: '/user',
        templateUrl: 'partials/user.html',
        controller: 'userController',
    })

    .state('user.one', {
        url: '/one',
        controller: 'oneController',
        views: {
            "menu": { templateUrl: "partials/client-menu.html" },
            "content": { templateUrl: "partials/one.html" }
        },
    });

    .state('user.two', {
        url: '/two',
        controller: 'twoController',
        views: {
            "menu": { templateUrl: "partials/client-menu.html" },
            "content": { templateUrl: "partials/two.html" }
        },
    });

    .state('user.three', {
        url: '/three',
        controller: 'threeController',
        views: {
            "menu": { templateUrl: "partials/admin-menu.html" },
            "content": { templateUrl: "partials/three.html" }
        },
    });

Now you can see "one" and "two" both use the same menu but "three" uses a different menu. This all works fine but is there a way to avoid duplicating the menu on "one" and "two".

Such as making a "user.client" state that uses the "user-menu.html" then "one" would be "user.client.one" instead and only have to specify the content.

I think the main problem is the

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

is on the grandfather of the "user.client.one" so how can it specify the content?

2 Answers2

1

I would say, that the trick is to move the "menu" view definition into parent state "user"

.state('user', {
    url: '/user',
    views: {
      "" : {
        templateUrl: 'partials/user.html',
        controller: 'userController',
      },
      "menu@user": { templateUrl: "partials/client-menu.html" },
     },
     ...

So, what happened? any child state of the "user" will already have the content of the "menu" filled, with the default templateUrl: "partials/client-menu.html"

Any other child, can override that...

.state('user.one', {
    url: '/one',
    controller: 'oneController',
    views: {
        // "menu": already set by parent
        "content": { templateUrl: "partials/one.html" }
     ....

.state('user.two', {
    url: '/two',
    views: {
        // "menu": set in parent
        "content": { templateUrl: "partials/two.html" }
        ...

.state('user.three', {
    url: '/three',
    controller: 'threeController',
    views: {
        // here we override that
        "menu": { templateUrl: "partials/admin-menu.html" },
        "content": { templateUrl: "partials/three.html" }
    ...

Maybe, check this Q & A for some more ideas about multi view nesting:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Hm ic so just make the client-menu default and if its a admin state override it. –  Jan 30 '15 at 19:15
  • YES Exactly... that's how I do handle this for state: entity / list / detail. Before the detail is selected... its area can contain some default content... Check the link in the answer... for some other point of view about the layout... But, my answer should be clear, I'd say. Hope it helps. Enjoy UI-Router anyhow – Radim Köhler Jan 30 '15 at 19:16
  • Thanks. I think a found another way using the absolute views if you see above. It seems to work so far. –  Jan 30 '15 at 19:33
  • Yes, it is variation of my solution. Glad if that works for you – Radim Köhler Jan 30 '15 at 19:34
  • Good luck with UI-Router ;) – Radim Köhler Jan 30 '15 at 19:54
0

I think a found a solution user the @ for absolute views:

.state('user', {
    url: '/user',
    templateUrl: 'partials/user.html',
    controller: 'userController',
})

.state('user.client', {
    url: '/client',
    views: {
        "menu": { templateUrl: "partials/client-menu.html" }
    },
})

.state('user.admin', {
    url: '/admin',
    views: {
        "menu": { templateUrl: "partials/admin-menu.html" }
    },
})

.state('user.client.one', {
    url: '/one',
    controller: 'oneController',
    views: {
        "content@user": { templateUrl: "partials/one.html" }
    },
});

.state('user.client.two', {
    url: '/two',
    controller: 'twoController',
    views: {
        "content@user": { templateUrl: "partials/two.html" }
    },
});

.state('user.admin.three', {
    url: '/three',
    controller: 'threeController',
    views: {
        "content@user": { templateUrl: "partials/three.html" }
    },
});

It feels abit cleaner but I'm not sure if its the right approach still.