This post is trending. 6,028 Views

Ionic Combining Side menu and Tabs

Side menu and tabs are two different kinds of navigation systems for mobile applications. More often than not we find ourselves in a situation where the application needs both style menus working seamlessly together. In this tutorial we will combine both navigation systems, tabs and side menus.
This tutorial assumes that you have ionic installed in your system and you know the basics of Ionic CLI. But, if you are new to Ionic framework please visit our Getting started with Ionic tutorial

The navigation combination in this tutorial is greatly inspired by the Ionic Conference Application by the Ionic Team. If you want more complete example please visit their repository on github

You can find the code for this tutorial at our github repository

Lets begin by creating a blank application

Open your terminal in working directory and type the following commands. If you do not understand the Ionic CLI commands, please go through our Ionic CLI cheatsheet.

ionic start IonNavs blank
cd IonNavs
ionic g page tabs
ionic g page tab1
ionic g page tab2
ionic g page special

You can delete the default home/ folder inside pages folder as we are not using this page.

Side menu

The menu pattern is always the same, we need to define the menu area and also the content area inside a view. In our case we construct the menu items from an array of pages which we will create in the next step.

Each button will automatically close the menu using menuToggle and we also dynamically set the icon and color of the button. Setting the color helps to reflect the changes of the tab bar also inside the menu!

Open app/app.html and update the content as

<ion-split-pane>
<ion-menu [content]="content">

  <ion-header>
    <ion-toolbar>
      <ion-title>Pages</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <ion-list>
      <button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
        <ion-icon item-start [name]="p.icon" [color]="isActive(p)"></ion-icon>
        {{p.title}}
      </button>
    </ion-list>
  </ion-content>

</ion-menu>

<ion-nav [root]="rootPage" main #content swipeBackEnabled="false"></ion-nav>
</ion-split-pane>

Then open app/app.component.ts and change the content as

import { Component, ViewChild } from '@angular/core';
import { Platform, NavController, Nav } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { Tab2Page } from './../pages/tab2/tab2';
import { Tab1Page } from './../pages/tab1/tab1';
import { TabsPage } from './../pages/tabs/tabs';
import { SpecialPage } from '../pages/special/special';

export interface PageInterface {
  title: string;
  name: string;
  component: any;
  icon: string;
  index?: number;
  tabName?: string;
  tabComponent?: any;
}

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = TabsPage;
  pages: PageInterface[] = [
    { title: 'Tab 1', name: 'TabsPage', component: TabsPage, tabComponent: Tab1Page, index: 0, icon: 'home' },
    { title: 'Tab 2', name: 'TabsPage', component: TabsPage, tabComponent: Tab2Page, index: 1, icon: 'contacts' },
    { title: 'Special', name: 'SpecialPage', component: SpecialPage, icon: 'shuffle' },
  ];
  @ViewChild(Nav) nav: Nav;
  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }

  openPage(page: PageInterface) {
    let params = {};
 
    // The index is equal to the order of our tabs inside tabs.ts
    if (page.index) {
      params = { tabIndex: page.index };
    }
 
    // If tabs page is already active just change the tab index
    if (this.nav.getActiveChildNavs().length && page.index != undefined) {
      this.nav.getActiveChildNavs()[0].select(page.index);
    } else {
      // Tabs are not active, so reset the root page 
      // In this case: moving to or from SpecialPage
      this.nav.setRoot(page.component, params);
    }
  }
 
  isActive(page: PageInterface) {
    // Again the Tabs Navigation
    let childNav = this.nav.getActiveChildNavs()[0];
 
    if (childNav) {
      if (childNav.getSelected() && childNav.getSelected().root === page.tabComponent) {
        return 'primary';
      }
      return;
    }
 
    // Fallback needed when there is no active childnav (tabs not active)
    if (this.nav.getActive() && this.nav.getActive().name === page.name) {
      return 'primary';
    }
    return;
  }
}

Lets build tabs page

Open pages/tabs/tabs.html and update as

<ion-tabs [selectedIndex]="myIndex">
  <ion-tab [root]="tab1Root" tabTitle="Tab 1" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Tab 2" tabIcon="contacts"></ion-tab>
</ion-tabs>

A very classic tab bar implementation with 2 tabs. The most important thing here is that we are able to dynamically change the selectedIndex of our tab bar from our app.component.ts.

Then open pages/tabs/tabs.ts and update as

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Tab1Page } from '../tab1/tab1';
import { Tab2Page } from '../tab2/tab2';

@Component({
  selector: 'page-tabs',
  templateUrl: 'tabs.html',
})
export class TabsPage {
 
  tab1Root: any = Tab1Page;
  tab2Root: any = Tab2Page;
  myIndex: number;
 
  constructor(navParams: NavParams) {
    // Set the active tab based on the passed index from menu.ts
    this.myIndex = navParams.data.tabIndex || 0;
  }
}

General structure for Tab1, Tab2 and special page.

Open pages/special/special.html and update as

<ion-header>
  <ion-navbar>
      <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Special</ion-title>
  </ion-navbar>
</ion-header>
 
<ion-content padding>
  This page has no tabs!
</ion-content>

Use the similar template structure for tab1.html and tab2.html, update title and content to make sure that you know when which page is loaded.

Conclusion

It might be tricky at first, trying to combine side menu and tabbed navigation but it is possible and not that difficult once you get the hang of it.
Thank you for taking your time to read this tutorial. Tell us what do you think or if you run into any problems in comment or in our facebook, twitter pages.

Related Posts

Advancde Ionic Components

If you are a Ionic developer, beginner or expert, you will love this project. Publicly being developed in github, ionic3-components repository hosts […]

%d bloggers like this: