An example of the Ionic 2 Menu Component

An example of the Ionic 2 Menu Component

This post is more than 2 years old.

In general, I find components in Ionic 2 to be simpler and easier to understand than their V1 versions, but for some reason, I was incredibly confused by the docs for working with the Menus component. Documentation exists of course, but it just didn't make sense to me. (I documented my problems in this issue for folks curious.) What follows is my own understanding of how to work with menus in Ionic 2 and some basic things to keep in mind. As always, remember I'm still learning this myself, so keep in mind I may get a detail or two wrong.

Before we continue, a few links:

  • First, the main component doc.
  • Then the related API doc.
  • Finally, the Sidemenu starter app. I did not use this when learning, and it does a few things differently. I'll talk about that at the end.

Alright, so to begin, I created a new Ionic 2 app with the blank template:

ionic start sidemenudemo blank --v2

This gave me a blank slate to begin by demo. In my demo, I want a site with three pages:

  • A home page
  • A cats page
  • A dogs page

Out of the box you get a home page, so I used the CLI to generate the two other pages:

ionic g page cats
ionic g page dogs

If you weren't aware, the CLI has a generate feature which can write boilerplate code for you. I highly recommend using it.

Alright, so the first thing you have to do when working with a side menu is create a new page. (See my note at the bottom!) So given my app has three pages, I needed a fourth page to host the menu. I created a new one called main.

If you want my demo, you can find it here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/sidemenudemo

ionic g page main

Since my app starts with the side menu, I decided to make main my root page for the app. So my first modification was to app.component.ts:


import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';

import { MainPage } from '../pages/main/main';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage = MainPage;

  constructor(platform: Platform) {
    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();
    });
  }
}

Essentially I just changed "Home" to "Main" in the import and the line where rootPage is set. So far so good. Now let's set up the main page to have my menu. Here is main.html:


<ion-menu [content]="mycontent">

	<ion-content>
		<ion-list>
			 <button ion-item menuClose (click)="openPage(homePage)">
				Home
			</button>
			<button ion-item menuClose (click)="openPage(catsPage)">
				Cats
			</button>
			<button ion-item menuClose (click)="openPage(dogsPage)">
				Dogs
			</button>
		</ion-list>
	</ion-content>

</ion-menu>

<ion-nav #mycontent [root]="rootPage"></ion-nav>

There are a couple of very important things here to note. First let's start on line one:


<ion-menu [content]="mycontent">

The [content]="mycontent" aspect confused the heck out of me. All it really means though is this: "When I load crap, I want you to load it in this container." You'll notice at the bottom I've got an ion-nav component that uses the #mycontent identifier there.

Now look at the menu code. Most of it is self-explanatory but I want to call out two things.

First, menuClose tells the menu to automatically close when a menu item is clicked. This is not the default, so most likely you will always want to add this.

Second, what's openPage(x) about? This is shown in the docs but not explained. Basically, you have to write the code to load new pages. This is easy of course, but the docs don't spell this out for you. Going from Ionic 1, I didn't have to do this because I simply used URLs I had already set routes up for.

Here is my main.ts:


import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { HomePage } from '../home/home';
import { CatsPage } from '../cats/cats';
import { DogsPage } from '../dogs/dogs';


@Component({
  selector: 'page-main',
  templateUrl: 'main.html'
})
export class MainPage {

  private rootPage;
  private homePage;
  private catsPage;
  private dogsPage;

  constructor(public navCtrl: NavController, public navParams: NavParams) {
    this.rootPage = HomePage;

    this.homePage = HomePage;
    this.catsPage = CatsPage;
    this.dogsPage = DogsPage;

  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad MainPage');
  }

  openPage(p) {
    this.rootPage = p;
  }

}

As you can see, openPage is pretty simple.

So that's it - but let me address one thing in particular when you compare my code to the SideMenu starter. For the application I was working on (an existing Ionic 1 app migrating to Ionic 2), the menu loads after an initial login screen. Therefore, using 4 pages (one for each page plus one for the menu) made sense. If you look at the SideMenu template though, they modify the main app.html file that is the root of the Ionic app itself. It is the first page, and the core I guess you could call it, so that made sense. If that's how your app starts up, I'd do that instead of creating another page as I've done here.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by terrycollinson1 posted on 1/7/2017 at 11:03 AM

I am really struggling with menus. I have a tabbed application where I want different menus on the different tab pages. Thought it would be simple. http://stackoverflow.com/qu... No answers yet

Comment 2 (In reply to #1) by Raymond Camden posted on 1/7/2017 at 2:36 PM

So to be clear, you have tabs, and each tab page has its own menu system?

Comment 3 (In reply to #2) by terrycollinson1 posted on 1/8/2017 at 9:07 AM

Hi Ray. Yes that's exactly right. I have 4 tabs excluding the home page. Each of the tabbed pages has its own menu.The code in stack overflow I have replicated on each of the pages but just changed the id's. I have had one working, one toggling another menu on another page all sorts of weird stuff.. You can see it not working here https://bou-bou-lodge.fireb...

Comment 4 (In reply to #3) by Raymond Camden posted on 1/9/2017 at 4:09 PM

Not to punt on you - but I'd suggest putting up a demo on codepen, then filing a bug report.

Comment 5 by AlphaOne posted on 1/19/2017 at 3:45 PM

Hi Ray,
This is just a shot in the dark, but does this mean that it is a better idea to create a menu using a page than using the MenuController as part of the main App page if you want to create a nested view as well?
If that's the case, how would you control the nav stack (especially when pushing to pages)? If I had to have a menu toggle button on a load of pages, would I be able to control which menu page it would link to?

Thanks for the post though, it really helped understand a few things that have been bothering me.

Comment 6 (In reply to #5) by Raymond Camden posted on 1/19/2017 at 8:17 PM

"This is just a shot in the dark, but does this mean that it is a better idea to create a menu using a page than using the MenuController as part of the main App page if you want to create a nested view as well?"

I honestly have no idea what you mean. :) It sounds like you mean you can create the menu entirely via code - and if so - that's something I haven't seen yet.

As for nested view - ditto. Not sure what you mean. To me, I have a menu with X views. It isn't necessarily nested.

"If that's the case, how would you control the nav stack (especially when pushing to pages)? If I had to have a menu toggle button on a load of pages, would I be able to control which menu page it would link to?"

Sorry - but I'm not understanding this question either. Right now the menu sets the rootpage, which should reset the nav stack, which makes sense to me.

Comment 7 (In reply to #6) by AlphaOne posted on 1/20/2017 at 2:56 PM

Hi Ray,
Yes, what I meant is that if you want true customisation of a menu, it looks like it would be a better idea to custom-code the menu using NavController in a separate page. At least that's the impression I get extrapolating from your post.

When I say 'nested view' I mean for instance if one would like to create a 2-level menu item. How would you go about pushing only the Menu controller if it is contained within the main app component? I've actually been trying to do this for a few days now without any success.

Regarding the nav stack, that's exactly what I meant. By setting the rootpage every time you select a menu item, the stack is reset. This isn't very intuitive if you need to cache information that the user was inputting for instance. Certainly, if there is no need to cache data across pages then this is the best option, but a problem arises if you have gone down the 'page' route of making a menu from scratch; how would one then ensure that the menutoggle would open the correct menu level?

Sorry if I was a bit vague and muddled, I was just putting my thoughts down to see if you had an idea.

Comment 8 (In reply to #7) by Raymond Camden posted on 1/23/2017 at 4:13 PM

You got me on all this. :) To the first part of your question - I'm still having issues wrapping my head around it. I hate to punt, but I'd say this would be good for the Ionic forums.

To your second one - well I'd say you can cache the data in the component. It shouldn't go away just because I leave the page and go to some othe rpage.

Comment 9 by Sudhir Govekar posted on 3/21/2017 at 4:50 AM

hi ,

i have created an ionic2 application which is having an sidemenu which has 3 options
1. login
2. register
3. add post [Q&A]

which are in app.html

for every option i have created one folder along with .ts, .css and .html file

login is done successfully but i am facing issue ..that how to hide the login and register options after successfully login

i have created one provider which will have access to my mongoose api which will check for isLogedin() [which will return TRUE or FALSE]

based on this condition i need to hide .. as soon as i login ....

i am new to ionic and i badly stuck ...so please
can anyone help me out on this please

thank you...

Comment 10 (In reply to #9) by manzar rizvi posted on 3/22/2017 at 5:45 AM

i am also facing the same issue i hide my menu after login but the problem is "the application doesnot change it without the application load 2nd ime" can you please help me to solve this issue

Comment 11 (In reply to #10) by Raymond Camden posted on 3/26/2017 at 12:37 AM

What about using *ngIf to show/hide the items?

Comment 12 by raghul posted on 3/31/2017 at 12:18 PM

in iphone is not working

Comment 13 (In reply to #12) by Raymond Camden posted on 3/31/2017 at 1:19 PM

Ok, but how? Do you see an error in console? What doesn't work exactly?

Comment 14 by Fred Baine posted on 4/5/2017 at 3:22 PM

So how would you (could you) programatically navigate from the dog page to the cat page?

Comment 15 (In reply to #14) by Raymond Camden posted on 4/5/2017 at 3:46 PM

Using the navController component.

Comment 16 by Samarth Agarwal posted on 4/17/2017 at 6:33 PM

How can be send parameters to the new rootPage?

Comment 17 (In reply to #16) by Raymond Camden posted on 4/17/2017 at 7:29 PM

As far as I know, you can't. You're basically setting a root value for the app. There's probably some way to do it - but none are coming to mind right now.

Comment 18 by Akarsha Purvachar posted on 5/25/2017 at 9:58 AM

Hi,
How to create side menu for any other page which is not root page?

Comment 19 (In reply to #18) by Raymond Camden posted on 5/25/2017 at 12:48 PM

You would just use the component on that page - it should just work. Did you try?

Comment 20 (In reply to #19) by Akarsha Purvachar posted on 5/25/2017 at 8:06 PM
Comment 21 (In reply to #20) by Akarsha Purvachar posted on 5/25/2017 at 8:09 PM

So this is my app.html file which has menu design, i want this in the home page, and my root page in login page... how should i include it in home page? and what should go in .ts file?
I'm really confused...

Comment 22 (In reply to #19) by Akarsha Purvachar posted on 5/25/2017 at 8:09 PM

<ion-menu [content]="nav">

<ion-header>

<ion-toolbar>

<ion-title>Menu</ion-title>

</ion-toolbar>

</ion-header>

<ion-content>

<ion-list>

<button ion-item="" (click)="onLoad(homePage)">

<ion-icon name="home" item-left=""></ion-icon>

Home

</button>

<button ion-item="" (click)="onLoad(historyPage)">

<ion-icon name="home" item-left=""></ion-icon>

History

</button>

<button ion-item="" (click)="onLoad(ezetapDetailsPage)">

<ion-icon name="Home" item-left=""></ion-icon>

Ezetap Details

</button>

<button ion-item="" (click)="onLoad(logout)">

<ion-icon name="logout" item-left=""></ion-icon>

Logout

</button>

<button ion-item="" (click)="onLoad(fAQsPage)">

<ion-icon name="Home" item-left=""></ion-icon>

FAQs

</button>

<button ion-item="" (click)="onLoad(aboutPage)">

<ion-icon name="Home" item-left=""></ion-icon>

About

</button>

</ion-list>

</ion-content>

</ion-menu>

<ion-nav [root]="rootPage" #nav=""></ion-nav>

Comment 23 (In reply to #21) by Raymond Camden posted on 5/25/2017 at 8:32 PM

Did you literally try just moving it to the home page?

Comment 24 (In reply to #23) by Akarsha Purvachar posted on 5/25/2017 at 9:01 PM

No i tried to include this code in component template with ` ` codes...
i don't know what i'm missing... its not working

Comment 25 (In reply to #24) by Raymond Camden posted on 5/26/2017 at 1:03 PM

You tried - but didn't say how it failed. Try making a test on codepen so we can see, and run, what you tried. I can't write this for you.

Comment 26 (In reply to #25) by Akarsha Purvachar posted on 5/29/2017 at 10:49 AM

Hi, i fixed it... i was going wrong in linking the pages.

Thank you.

Comment 27 (In reply to #26) by Raymond Camden posted on 5/29/2017 at 3:17 PM

Glad you got it.

Comment 28 (In reply to #27) by Chris posted on 5/31/2017 at 10:24 PM

For anyone else who came across this hunting for a solution to a menu on a sub page (and not on any other pages) - you still put the <ion-menu> and <ion-nav> components in app.html (not in the sub page as Raymond is suggesting) and just control whichever you need from the sub page component. See http://ionicframework.com/d... 'Multiple Menus on the Same Side' for more info. But thanks Raymond for all the great articles... : )

Comment 29 (In reply to #28) by Raymond Camden posted on 5/31/2017 at 10:25 PM

Ah, that *does* make sense - sorry for leading folks down the wrong path here. :)

Comment 30 (In reply to #29) by Chris posted on 5/31/2017 at 10:37 PM

If you just want a menu for one page (like in my case a layers list for a map page) It makes more sense for it to be defined on the sub page component because you want to to be able to hook into any menu item events from the sub page component, not from the app component e.g. if you have an <ion-item (click)="doSomething()"> in the menu then you'll need the doSomething() method in the app component, not the sub page component... which is a bit of a pain.

Comment 31 (In reply to #30) by Chris posted on 5/31/2017 at 10:45 PM

...but is perhaps best handled using Events (http://ionicframework.com/d...

Comment 32 (In reply to #1) by Chris posted on 5/31/2017 at 11:05 PM

See answer on stackoverflow...

Comment 33 by Alexandre Nakad posted on 9/8/2017 at 5:25 AM

HI,
how can I make the menu (side menu) fixed, i.e. showing all the time on tablets?
I couldn't find anything in the docs.
Thanks

Comment 34 (In reply to #33) by Raymond Camden posted on 9/8/2017 at 1:05 PM
Comment 35 by PrudhvirajRoyal Dandi posted on 9/13/2017 at 5:35 PM

same menu i want to use in many pages and in some pages it should be disable like login page and signup page ..how?

Comment 36 (In reply to #35) by Raymond Camden posted on 9/14/2017 at 4:47 PM

Just not include it there?

Comment 37 by Musa Sesay posted on 11/17/2017 at 12:30 AM
Comment 38 by Musa Sesay posted on 11/17/2017 at 12:33 AM

I have some error with ionic project
at the constructor to create menu

Comment 39 (In reply to #38) by Raymond Camden posted on 11/17/2017 at 2:35 AM

Does it say what the error is?

Comment 40 by Oliver Waterkamp posted on 12/5/2017 at 1:24 PM

Thank you very much for the article and the sourc-code (https://github.com/ionic-te....
It helped me to solve the problem.
I missed the part with the reference to the navigation via ViewChild to navigate from the sidemenu.
This important part was not visible in your article (sorry I'm new in Angular and didn't know about this ViewChild reference possibility).
But it was very good visible within the provided source-code.
Thanks for helping me to solve my problem.

Regards from Zurich, Switzerland
Oliver

Comment 41 (In reply to #37) by Oliver Waterkamp posted on 12/5/2017 at 1:27 PM

homePage: Component --> homePage:any (line 9)

Comment 42 by Anand Raj posted on 3/4/2018 at 6:20 AM

Hi, Thnaks for your doc. I am facing one problem with menuClose in Ionic3. side-menu is not closing even after taping on the menu item multiple times.

Comment 43 (In reply to #42) by Raymond Camden posted on 3/5/2018 at 1:42 PM

Best I can suggest is creating a CodePen version of this that recreates the issue and reporting it to Ionic.

Comment 44 by Marc Fernandez posted on 5/28/2018 at 12:52 PM

Hi. First of all, thanks for this great tutorial. I raise an issue that has arisen in an app that I am developing. I have implemented the code exactly like yours. In my homePage.html (apart from the menu) I have put several buttons to go to the different sections of the page with "<button (click)=" openPage (notificationsPage) ">" and in JS I have put "this.navCtrl.setRoot (page);".

The point is that if I click on any of those buttons in the homePage.html, I am well directed to the page, but the menu button to go to the homepage again does not work (but it works with any other element).

Any suggestions?

Comment 45 (In reply to #44) by Raymond Camden posted on 6/4/2018 at 2:16 PM

Best I can suggest is to make a CodePen recreation of this. That will help me debug. But I'm very rusty with Ionic lately.