$state.go not working for nested states

I am trying to navigate between nested states but it is not working as expected which probably indicates that there is something obvious that I don’t understand.

The basic idea is to navigate between the state “tab.info” and the state “tab.info.about”. I would like a back button to show up automatically. This is my first time using deeply nested routing states.

The problem I am having is that the tab.info.about page is not showing up at all so I can’t determine if the back button is appearing correctly.

This is what the routing configuration and controllers look like. Note the ‘tabs.info’ and ‘tabs.info.about’ states.

angular.module('ionicApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider
    .state('tab', {
        url: "/tab",
        abstract: true,
        templateUrl: "templates/tabs.html"
    })
   .state('tab.home', {
        url: '/home',
        views: {
            'tab-home': {
                templateUrl: 'templates/tab-home.html',
                controller: 'HomeCtrl'
            }
        }
    })
   .state('tab.search', {
        url: '/search',
        views: {
            'tab-search': {
                templateUrl: 'templates/tab-search.html',
                controller: 'SearchCtrl'
            }
        }
    })
   .state('tab.info', {
        url: '/info',
        views: {
            'tab-info': {
                templateUrl: 'templates/tab-info.html',
                controller: 'InfoCtrl'
            }
        }
    })
    .state('tab.info.about', {
        url: '/about',
        views: {
            'tab-info': {
                templateUrl: 'templates/tab-info-about.html',
                controller: 'InfoAboutCtrl'
            }
        }
    })
    ;
    $urlRouterProvider.otherwise('/home');
})
.controller('InfoCtrl', function($scope, $state) {
    console.log('InfoCtrl');
    $scope.about = function() {
        $state.go('tab.info.about');
    };
})
.controller('InfoAboutCtrl', function($scope) {
    console.log('InfoAboutCtrl');
})
.controller('SearchCtrl', function($scope) {
    console.log('SearchCtrl');
})
.controller('HomeCtrl', function($scope) {
    console.log('HomeCtrl');
})
;

This what the HTML looks like:

<html ng-app="ionicApp">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> 
    <title>Nested Tab States Example</title>
    <link href="http://code.ionicframework.com/1.0.0-beta.11/css/ionic.css" rel="stylesheet">
    <script src="http://code.ionicframework.com/1.0.0-beta.11/js/ionic.bundle.js"></script>
  </head>
  <body>

    <ion-nav-bar class="nav-title-slide-ios7 bar-positive">
      <ion-nav-back-button class="button-icon ion-ios7-arrow-back">
        Back
      </ion-nav-back-button>
    </ion-nav-bar>

    <ion-nav-view animation="slide-left-right"></ion-nav-view>

    <script id="templates/tabs.html" type="text/ng-template">
      <ion-tabs class="tabs-icon-top tabs-positive">

        <ion-tab title="Home" icon="ion-ios7-home" href="#/tab/home">
           <ion-nav-view name="tab-home"></ion-nav-view>
        </ion-tab>

        <ion-tab title="Search" icon="ion-ios7-search" href="#/tab/search">
           <ion-nav-view name="tab-search"></ion-nav-view>
        </ion-tab>

        <ion-tab title="Info" icon="ion-ios7-information-outline" href="#/tab/info">
            <ion-nav-view name="tab-info"></ion-nav-view>
        </ion-tab>

      </ion-tabs>
    </script>

    <script id="templates/tab-info.html" type="text/ng-template">
      <ion-view title="Information">
          <ion-content class="padding">
          <p>Lot's of interesting information here. 
             For more stuff click the "About" button.
          </p>
          <a class="button icon-right ion-chevron-right"
             ng-click="about()">
            About
          </a>
          </ion-content>
      </ion-view>
    </script>

    <script id="templates/tab-info-about.html" type="text/ng-template">
      <ion-view title="About">
          <ion-content class="padding">
            <p>About us.</p>
            <p>Back button should appear in the upper left hand corner.</p>
          </ion-content>
      </ion-view>
    </script>

    <script id="templates/tab-search.html" type="text/ng-template">
      <ion-view title="Search">
          <ion-content class="padding">
            <p>Search</p>
          </ion-content>
      </ion-view>
    </script>

    <script id="templates/tab-home.html" type="text/ng-template">
      <ion-view title="Home">
          <ion-content class="padding">
            <p>Home</p>
          </ion-content>
      </ion-view>
    </script>

  </body>
</html>

Any insights would be greatly appreciated.

Thanks.

An codepen for this kind of questions would be awesome!

For now, without actually trying, I would suggest to try changing:

To:

state('tab.info-about', {
        url: '/about',
        views: {
            'tab-info': {
                templateUrl: 'templates/tab-info-about.html',
                controller: 'InfoAboutCtrl'
            }
        }
    })

Because you need to make tab.info an abstract state to be able to have childstates… Not sure if this fixes all your problems though :slight_smile:

Thank you. I appreciate you taking the time to respond.

I am aware that I can collapse the states to one level (I should have mentioned that in the original question) but that seems artificial. Do you know why a nested state will not work? Why does tab.info need to be abstract? It is just a state transition. I am clearly missing something obvious so if you could point me to any relevant documentation, i would really appreciate it.

Code pen: http://codepen.io/jlinoff/pen/bitup/?editors=101

Cheers.

That suggestion worked perfectly and the back button appeared as expected.

Thank you.

Bascially, when you have nested views, you have nested states. If you do not have nested views, you do not have nested states. That’s what I’ve concluded after playing around this afternoon, couldn’t find another way to have nested states really… Don’t know how the internals work though, didn’t have any time yet to dive into that.

I understand correctly that your issues have been fixed?

That may be it.

However, I think there is something fundamental that I don’t understand about states. From what I read in the angularjs documentation (http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state) there doesn’t seem to be an obvious reason why aribitrary nesting of states shouldn’t work. Note the mention of the grandchild state under the “go” documentation but, since my stuff is now working after refactoring based on your help, I will probably not dig into it for awhile but, at some point, I would really like to understand it.

I understand correctly that your issues have been fixed?

Yes, thank you.

I will probably not dig into it for awhile but, at some point, I would really like to understand it.

Exactly what I thought, I totally agree!

Glad you’ve been helped :slight_smile:

That suggestion worked perfectly and the back button appeared as expected.

What suggestion are you referring to? I am having similar issues and any help on how you re-factored would be awesome!

Thanks

He said that in reply to my post at: $state.go not working for nested states hope this helps

Change your code:
> .state(‘tab.info.about’, {

        url: '/about',
        views: {
            'tab-info': {
                templateUrl: 'templates/tab-info-about.html',
                controller: 'InfoAboutCtrl'
            }
        }
    })

to

.state(‘tab.info.about’, {
url: ‘/about’,
views: {
‘tab-info@tab’: {
templateUrl: ‘templates/tab-info-about.html’,
controller: ‘InfoAboutCtrl’
}
}
})

usage html same:

<a ui-sref=".about"></a>

it’s working for me :slight_smile:
Thread here : http://stackoverflow.com/questions/21818515/angularjs-nested-states-3-level

Thanks much for posting this. Saved the day. Hours looking at why my ionic $state.go() was not working!