Using Nested States With The AngularJS UI-Router

When coding, it is good practice to reduce duplicating your code as much as possible.  When you build a website, multiple pages may be grouped with specific layouts that are used any number of times.  You don’t want to duplicate your layout code across these pages.

A common thing to do in web design is to use templating.  This exists similarly across many web languages, but in this example I’m going to demonstrate how to do this with AngularJS and the UI-Router extension.

To be specific we are going to accomplish the following:

  1. Create a root layout that will span every page
  2. Create a child layout that will be nested in the root layout.  The child layout will contain a foundation to all settings pages
  3. Create content views for each of the settings pages

With this knowledge you’d be able to create a multi-layout project.  In this project, we are going to have the following directory and file structure:

  • templates
    • settings.html
    • account.html
    • profile.html
  • js
    • angular-ui-router.min.js
    • app.js
  • index.html

Start by downloading the UI-Router library and including it in your project.  Your index.html page should look something like this:

Notice the index.html page has all our JavaScript and CSS includes.  It also has the following two lines:

I added the text Index Level to make it obvious that the index.html code is used in our page.  It represents level one of three in our nesting line.  The ui-view line is where the next layer will display.

Now let’s crack open the settings.html page.  This page will pretty much just contain a menu system for navigating between settings pages.  Often websites will have a separate UI system for settings pages, but yet it will keep a trend.

Notice the highlighted lines above.  The first two are responsible for loading the next level of nesting which is nesting level three.  The third line is where level three will be loaded into.  I threw a line of code in there to show us that the settings level was loaded.

Now we are going to add the code for the third level of nesting.  Open profile.html and add the following lines:

Do the same for account.html, but this time add the following content:

When a third level page is loaded it will show the root level, settings level, and content level content.  So at this point we only did the UI work.  We still need to code the JavaScript that will be responsible for tying everything together.

Open the app.js file and add the following code:

Time to break down what the above code means.  Take a look at the following lines:

The above state represents the settings level layout.  It will never be called directly because it is nothing more than a layout.  It cannot exist on its own in the scenario that we’re building.

In the above code, notice in particular settings.profile.  This has very specific meaning.  It means that we are going to call the settings state as well as the profile state.  It is how we accomplish nesting.  States are object based so every time we add to the parent settings element it means we are going to render the page inside of it.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • studiorooster

    Nic…this is a brilliant example of simplicity and comes at a great time for a project I am starting that has a ton of content pages with many nested views (sub-directories) and this is a perfect solution for creating shared sub-menus instead of using ng-include, which was what I was about to do.

    Thank you for the timely tut…

    • No problem. Thanks for the compliment!

  • Sander Sink

    Nice post!

    Nested states can be also used to store language in url path: http://fadeit.dk/post/angular-translate-ui-router-seo

    Sander

  • ashutosh Ray

    Hi Nic

    I have a question like as we are add partial html with state approach. How can we add our JS file with state approach?

    • Can you give me an example of what you’re trying to do? I’m not quite sure what you’re after.

      Regards,

      • ashutosh Ray

        In you above example all the JS is contain in one file app.js. In my app for each template a separate JS file are there. I want to add those JS file at the time when template is getting load

        • Why not just load the particular JS file in your partial file?

          • ashutosh Ray

            I try with like below example but its not working
            .state(‘settings’, {
            url: ‘/settings’,
            templateUrl: ‘templates/settings.html’,
            js:’templates/settings.js’
            })

          • I mean’t add script tags to the bottom of your settings.html file.

  • barsv

    i haven’t read even a few lines, but there is already a pop-up asking for a donation. is it now considered to be ok? i even don’t know yet if it’s a good resource. i already start to doubt.

    • Sorry, that was a bug in my WordPress plugin and you’re the only one that reported it to me. Should be fixed now.

      Best,

  • Bang

    @nicraboy:disqus , hey there, did you realize for yourself, changing main layout depend of environment, means like:

    main layout
    dashboard layout
    main layout + (for example products filters and recent viewed items)

    Maybe you found finished someone else’s solution?
    Thanks in advance for your answer!

    • I have no idea what you’re asking, sorry.

      • Thomas Joseph Greco

        I just received the same comment on this post of mine – http://www.sitepoint.com/write-modular-code-angular-ui-router-named-views/

        • Bang

          Yeap, because i am trying to find out well-designed solution from more experienced developers, because i haven`t found anything good.

          Maybe i didn’t explain correct in my first message
          Sorry for bad English:)

          • If you want a good answer, you’ll ask one person instead of spamming the entire internet trying to get an expedited response. Doing that will get you no responses.

          • Bang

            I am not sure that asking two persons, the blogs which I usually read, can be called spamming.

      • Bang

        Anyway thanks for answer!

      • Asaf Cohen

        Hey @nicraboy:disqus , great post. thanks!
        Let’s say we want to re-create wordpress. or any website with frontend and backoffice.
        How would you implement this such of thing?

        I thought about the following template structure:

        backoffice
        — layout
        — header.html
        — footer.html
        — menu.html
        — users
        — list.html
        — create.html
        — edit.html
        frontend
        — layout
        — header.html
        — footer.html
        — menu.html
        — about.html
        — contact.html
        …….

        How do you suggest to implement this such of thing?

        Thanks!

        • In that scenario you would have two levels. A parent layout state and a child users state.

  • Atta-ur- Rehman

    I am using nested ui routing but my header title will not change after change the route ?