How to set up sidemenu with tabs in Ionic?

2019-02-17 05:44发布

问题:

In my opinion having a sidemenu, for things like settings and about pages, combined with tabs for the main app is a pretty essential and standard app interface. Things like Google's Messenger app use this.

I'm struggling to get it working and I see there are a lot of questions about it with very little satisfactory information. I've combined a sidemenu with swipeboxes fine. This should be just as easy. I used to use jQuery Mobile for my apps, which is much more clunky than Ionic but doing an interface like this is easy and it works well.

The problem I'm having is the tab templates don't load into the tabs. This may be something silly I'm missing but here is my app.js code snippet:

config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: "/app",
    abstract: true,
    templateUrl: "templates/menu.html",
    controller: 'AppCtrl'
  })

  .state('app.tabs', {
    url: "/tabs",
    views: {
      'menuContent': {
        templateUrl: "templates/tabs.html"
      }
    }
  })

.state('tab.tab1', {
      url: 'tab/tab1',
      views: {
        'tab-tab1': {
          templateUrl: 'templates/tab-tab1.html',
          controller: 'tab1Ctrl'
        }
      }
    })

.state('tab.tab-tab2', {
      url: 'tab/tab2',
      views: {
        'tab-tab2': {
          templateUrl: 'templates/tab-tab2.html',
          controller: 'tab2Ctrl'
        }
      }
    })

.state('tab.extras', {
    url: 'tab/extras',
    views: {
      'tab-extras': {
        templateUrl: 'templates/tab-extras.html',
        controller: 'AccountCtrl'
      }
    }
  })

    .state('app.about', {
      url: "/about",
      views: {
        'menuContent': {
          templateUrl: "templates/about.html",
          controller: 'aboutCtrl'
        }
      }
  });
  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/app/tabs');
});

The side menu works fine and I can navigate with it to the about page or back to the tabs. The tabs work in that they change focus and the icons change colour, but the templates don't load into them. I've tripple double checked the url names.

Does anyone know how to do this? If I've made a small error somewhere and get it working I'll Codepen this as an example of how to create this, imho, much needed interface.

Edit: As requested.

<ion-tabs class="tabs-icon-top tabs-color-active-assertive">  

  <ion-tab title="tab1" icon="ion-man" href="#/tab/tab1">
    <ion-nav-view name="tab-tab1"></ion-nav-view>
  </ion-tab>

  <ion-tab title="tab2" icon="ion-person-stalker" href="#/tab/tab2">
    <ion-nav-view name="tab-tab2"></ion-nav-view>
  </ion-tab>

  <ion-tab title="Extras" icon="ion-heart" href="#/tab/extras">
    <ion-nav-view name="tab-extras"></ion-nav-view>
  </ion-tab>

</ion-tabs>

I think they all match up, no?

Note - with regards to the query about this being a duplicate; my app is a tabbed app with a side menu on the base page. The other question is about an app with a series of sections, one of which has tabs. It's a different structure altogether.

回答1:

I think your routing is a bit off - your child states for the tabs aren't fully declared. You've declared them like this

.state('tab.tab1', {

...and you've never declared the parent tab state. So they are left 'hanging' until the parent state is declared. ui-router will just ignore them until this happens.

Try this

config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: "/app",
    abstract: true,
    templateUrl: "templates/menu.html",
    controller: 'AppCtrl'
  })

  .state('app.tabs', {
    url: "/tabs",
    views: {
      'menuContent': {
        templateUrl: "templates/tabs.html"
      }
    }
  })

.state('app.tabs.tab1', {
      url: '/tab1',
      views: {
        'tab-tab1': {
          templateUrl: 'templates/tab-tab1.html',
          controller: 'tab1Ctrl'
        }
      }
    })

.state('app.tabs.tab2', {
      url: '/tab2',
      views: {
        'tab-tab2': {
          templateUrl: 'templates/tab-tab2.html',
          controller: 'tab2Ctrl'
        }
      }
    })

.state('app.tabs.extras', {
    url: '/extras',
    views: {
      'tab-extras': {
        templateUrl: 'templates/tab-extras.html',
        controller: 'AccountCtrl'
      }
    }
  })

    .state('app.about', {
      url: "/about",
      views: {
        'menuContent': {
          templateUrl: "templates/about.html",
          controller: 'aboutCtrl'
        }
      }
  });
  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/app/tabs');
});

And better / clearer to use ui-sref rather than href in your tabs template - easier to see what state something maps to

<ion-tabs class="tabs-icon-top tabs-color-active-assertive">  

  <ion-tab title="tab1" icon="ion-man" ui-sref="app.tabs.tab1">
    <ion-nav-view name="tab-tab1"></ion-nav-view>
  </ion-tab>

  <ion-tab title="tab2" icon="ion-person-stalker" ui-sref="app.tabs.tab2">
    <ion-nav-view name="tab-tab2"></ion-nav-view>
  </ion-tab>

  <ion-tab title="Extras" icon="ion-heart" ui-sref="app.tabs.extras">
    <ion-nav-view name="tab-extras"></ion-nav-view>
  </ion-tab>

</ion-tabs>

Not tested it but I think that should fix it! Any errors in the console BTW?