Combining sidemenu navigation with nested tabbed interface?

We are building a ‘sidemenu-style’ app but would like to use a tabbed view in one of the screens. Has anyone managed to do this? We’re using the ui-router and I imagine the tabbed page would need to be a nested view with its own states. Im not sure how to go about building that and was hoping someone has already done it and can offer advice/hints/tips/examples.

Here is an example, it probably has a few minor updates to be made with the current beta since it was built a few months ago.

1 Like

Beware that there are a few bugs with Ionic’s latest version (1.0.0-beta.12) in handling tabs and side menus, as described here:


But works perfectly in older versions of Ionic. Good luck!

1 Like

After I posted the question above, I managed to build something that works but I wanted to ask a question about states. Right now, my tabs screen has a "home" state that acts as a parent for the tabs navigation. Each tab has its own state that is a child state of the home state, e.g. 'home.tab1', 'home.tab2', etc. But upon first entering the home state I want tab1 to render automatically. How do I do that? Do I need to check the current state and transition state? If so, do I also need to do that every time or is there a way to set some flag so it only does it the first time?

1 Like

If you looked at my Codepen above, what I do is have my “home” screen as an abstract view, and actually make my “tab1” as my default view (and also linked from the side menu). So, the first time you come in, you’re sent to “tab1” automatically.

Now, anytime you navigate away from the tab view and come back, you’re always sent to “tab1”, so not sure if that fills your first entering the home state requirement, but does make things easy and predictable to the user.

Yes, the abstract state was what was missing - thanks! I made the link into the tabs screen, transition directly into the child state. The only problem left now is one where I can’t seem to transition between child states, i.e. I have an href attribute in ion-tab which is a direct URL to the child state but this doesn’t work - clicking on a tab goes out of the tabs screen, back to the screen that I intially used to enter the tabs screen.

Sounds like maybe the “ion-nav-view” in each of your tabs doesn’t match the name of the “views” in your route states, or you’re not setting the view name in your states? For example, if your tab is something like:

<ion-tab title="tab1" href="#/home/tab1">
   <ion-nav-view name="content-tab1"></ion-nav-view>
</ion-tab>

then your state should look something like:

.state('home', {
   url: '/home',
   abstract: true,
   template: 'templates/home.html'
})
.state('home.tab1', {
   url: '/tab1',
   views: {
      'content-tab1': {
         templateUrl: 'templates/tab1.html',
         controller: 'Tab1Ctrl'
      }
   }
})

You want to a) define the view name for each of your tabs (and give them all different names), and b) make sure the names in your route states match the names of your ion-nav-view elements.

Yes, I think I am doing that:

<ion-view title="Connect">
  <ion-nav-buttons side="left">
    <button side="left" menu-toggle="left" class="button button-icon icon ion-navicon"></button>
  </ion-nav-buttons>
  <ion-tabs class="tabs-top tabs-striped">
    <ion-tab title="Friends" href="#/app/connect/friends">
      <ion-nav-view name="friends"></ion-nav-view>
    </ion-tab>
    <ion-tab title="Groups" href="#/app/connect/groups">
      <ion-nav-view name="groups"></ion-nav-view>
    </ion-tab>
    <ion-tab title="Invite" href="#/app/connect/invite">
      <ion-nav-view name="invite"></ion-nav-view>
    </ion-tab>
  </ion-tabs>
</ion-view>

And my corresponding states:

.state('app.connect', {
    url : "/connect",
    abstract : true,
    views : {
        'menuContent' : {
            templateUrl : "templates/connect.html",
            controller : 'ConnectCtrl'
        }
    }
})

.state('app.connect.friends', {
    url : "/connect/friends",
    views : {
        'friends' : {
            templateUrl : "templates/friends.html",
            controller : 'FriendsCtrl'
        }
    }
})

.state('app.connect.groups', {
    url : "/connect/groups",
    views : {
        'groups' : {
            templateUrl : "templates/groups.html",
            controller : 'GroupsCtrl'
        }
    }
})

.state('app.connect.invite', {
    url : "/connect/invite",
    views : {
        'invite' : {
            templateUrl : "templates/invite.html",
            controller : 'InviteCtrl'
        }
    }
});

I think the problem is with your route config. The “.” in your state names is kind of like inheritance, especially when it comes to paths. For example, your “Friends” route state should drop the “/connect” from your URL (since it’s “inherited” from “app.connect”) and look something like this instead:

.state('app.connect.friends', {
    url : "/friends",
    views : {
        'friends' : {
            templateUrl : "templates/friends.html",
            controller : 'FriendsCtrl'
        }
    }
})

Give that a try and see if it helps any.

That seems to have done the trick - the tabs work as expected. My confusion was with the different kinds of URLs, i.e. “state” URLs vs. browser URLs Thanks very much for the assist :smile:

Heh. Yea, that tripped me up too when I first ran into it. Glad I could help.

Another small problem: normally when transitioning to another state the sidemenu will add a BACK button to the top nav bar but I dont see this in my “tabs” screen, even though it exists in the app.connect template.

I believe this is on purpose. Ionic treats the tabs as separate “views”, and so handles the history for each tab separately. The benefit of this approach is that the app can “remember” where you left off at when you return to a specific tab.

AFAIK, there’s no way to use a “shared” history where it would detect switching tab views like you’re expecting, unfortunately.

From your description it sounds like my app.connect state, which acts as the parent for the tabs, maintains history for the tabs too so it knows nothing about the sidemenu. That being said is there a way to query the sidemenu and then add a back button if I need to? Right now, I transition from the sidemenu into the tabs screen and there’s no way to go back except by opening the sidemenu and tapping a “home” button.

Not that I know of, no.

There is the AngularJS event $locationChangeSuccess that you could probably capture and build your own history stack with, and could figure out where you came from when landing on a tab and building the back button yourself.

The event doesn’t tell you where you came from, unfortunately, so you’d need to capture the event on every view and push the current page URL onto a global history array to be able to detect how you got to that page. Not elegant, but might suit your needs.

Hi Guys, I have implemented the above into my project, but for some reason my home screen has buttons on it, when i click on the buttons it does not do a transition also there is no back button, any ideas?

Thanks

the only example i could found on that issue is using 0.9.26 which pretty outdated:

I kinda have something working here:

I’m trying to optimise it so I have less and less DOM to carry around, because for now the transitions on android are rather slow! If anyone is keend to help me improve that?

(I opened an issue on stack overflow here: http://stackoverflow.com/questions/30021401/ionic-sidemenu-multitabs-uirouter)

But How I make tabs changed to other color after selected like ion-tab method?

I have a problem with ion-tab method cannot scrollable and have been trying to fix with many ways but still no luck

If some attribute changes when selected then you can probably use CSS to color the tab when the attribute is set, no?