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.
Archived Comments
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
So to be clear, you have tabs, and each tab page has its own menu system?
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...
Not to punt on you - but I'd suggest putting up a demo on codepen, then filing a bug report.
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.
"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.
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.
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.
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...
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
What about using *ngIf to show/hide the items?
in iphone is not working
Ok, but how? Do you see an error in console? What doesn't work exactly?
So how would you (could you) programatically navigate from the dog page to the cat page?
Using the navController component.
How can be send parameters to the new rootPage?
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.
Hi,
How to create side menu for any other page which is not root page?
You would just use the component on that page - it should just work. Did you try?
https://uploads.disquscdn.c...
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...
<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>
Did you literally try just moving it to the home page?
No i tried to include this code in component template with ` ` codes...
i don't know what i'm missing... its not working
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.
Hi, i fixed it... i was going wrong in linking the pages.
Thank you.
Glad you got it.
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... : )
Ah, that *does* make sense - sorry for leading folks down the wrong path here. :)
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.
...but is perhaps best handled using Events (http://ionicframework.com/d...
See answer on stackoverflow...
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
Look here: https://github.com/ionic-te...
same menu i want to use in many pages and in some pages it should be disable like login page and signup page ..how?
Just not include it there?
https://uploads.disquscdn.c...
I have some error with ionic project
at the constructor to create menu
Does it say what the error is?
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
homePage: Component --> homePage:any (line 9)
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.
Best I can suggest is creating a CodePen version of this that recreates the issue and reporting it to Ionic.
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?
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.