Click Here for TL;DR

Part 2 of this series were going to talk about nested states. Specifically states nested deeper than two levels.

UI Router

Ionic uses Ui Router to handle all of it’s routing and state change.  Ionic uses many  directive throughout it’s framework to add functionality or mimic functionality of angular directives.  Ionic uses ion-nav-view to replace UI Routers ui-view and add additional functionality. From their site:

The ion-nav-view is our container. Ionic’s router will look for this directive throughout our code to insert templates. ion-nav-view supports inheritance, named views, and other features that we will discuss in depth throughout this series.

Note: If you’re familiar with angular-ui-router, ion-nav-view is equivalent to ui-view. On top of that, ion-nav-view provides for animations, history, and more.

Below is an example of a simple route and view as you might find in Ionic’s starter project.  The code below will be referenced throughout this article. It is assumed that you are familiar with both Ionic and Ui-Router.  For a more information on Ionic click here, for more information on UI Router click here.

//app.js file

  .state('tab', {
    url: "/tab",
    abstract: true,
    templateUrl: "templates/tabs.html"
  .state('tab.account', {
    url: '/account',
    views: {
      'tab-account': {
        templateUrl: 'templates/tab-account.html',
        controller: 'AccountCtrl'
  .state('tab.account.settings', {
    url: '/settings',
    views: {
      'tab-account@tab': {
        templateUrl: 'templates/tab-account-settings.html',
        controller: 'SettingsCtrl'

Using UI Router in Ionic

The above example has a root state of 'tab'. All other states are children of this state. This state has tabs.html as it’s template where we might see something like this:

<!-- Account Tab -->
  <ion-tab title="Account" icon-off="ion-ios7-gear-outline" icon-on="ion-ios7-gear" href="#/tab/account">
    <ion-nav-view name="tab-account"></ion-nav-view>

Notice <ion-nav-view name="tab-account" ... this is declaring this view as a holder for any template declared to go in the tab-account view.

tab.account.settings is a child state of tab.account. In the example above the view name is listed as tab-account@tab. This is using UI Routers “absolute name” method. This says to inject the states template into the tab-account view found in the tab state.

An alternative method to this is the name a new view for tab.account.settings and placing a <ion-nav-view name="new-name" ... in the tab.account state’s template.

You will have to experiment and decide which method works best for your use case. You will also notice how nesting your states differently will affect Ionic’s Automatic Navigation or “Breadcrumbs” along with how it affects Ionic’s transition animations.

One complaint I do have regarding Ionic’s Automatic Navigation. If you have a menu button that leads a user to a child state and the user navigated deeper into more child states from there, Ionic will remember this. That means the next time a user clicks that navigation button it will take them to the nth child state they were last at, not the state which the navigation button links to.

The only work around I have found for this so far is to hook said navigation button up to a function in your Controller where you move the user via a $state.go('state-name'). This will ensure the user always travels to that state when the button is clicked.

I do not like this solution but it is the only one I have found to work so far.

I hope this information was as helpful to you as it was to me!

In The End

Ionic uses UI Router to handle route and states. You can learn more about this on both UI Router and Ionic’s website.

<ion-nav-view name="view-name"... is equivalent to UI Routers <ui-view="view-name"... and using UI Router’s Absolute Name method allows you to display child states in their parents entire view.

Using different methods to nest and display your states will change the behavior of Ionic’s Automatic Navigation and their automatic transitioning between states.

Pro Tip: Manipulate DOM with Chrome’s Console

When you select a DOM Node with the Inspect Element tool chrome automatically assigns it to a variable. $0. If you want to do quick and dirty testing in the console before taking the time to code up a solution you can manipulate said element in Chrome’s Console using this variable. For example adding a CSS class with Jquery. $($0).addClass('myClass')

Join the Conversation


  1. Hi Jacob,
    I found your post very easy to follow.
    I had run into a similar problem re Ionic’s default handling of navigation (the ‘< Back' button) and child states and the work around was add to add a ion-nav-bar to the ion-side-menu-content and an ion-nav-buttons to each view.





  2. Very useful article! I was struggling with this issue, and I read numerous solutions on SO and other sites about nested views for a deeper level than 2, but this article gave me what I really needed. Spent half of the day trying to figure out what’s wrong with my code, and finding out in the end that all I needed was to nest a view like this: ‘tab-account@tab’. Thank you! 🙂

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.