-
Notifications
You must be signed in to change notification settings - Fork 24
Ionic_Menu
In this post I'm going to write about implementing a "side menu" inside the Ionic app. My Native Android version already has this menu since it was created from a template, but for Ionic I have to implement it on my own - luckily, that's not too hard.
Creating a menu involves creating an HTML template for that menu's interface. For this I created a new app.html file within the app folder and added the following code.
<ion-menu [content]="content">
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
<ion-content>
<ion-list>
<button ion-item *ngFor="#p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav id="nav" #content [root]="rootPage"></ion-nav>
The last line (apart from the #content
) was already set inside the app.js file as the app's template. Everything within <ion-menu>
tags is the HTML code for the side menu that will be displayed. Let's explain this code a little bit by starting with the following piece:
<ion-nav id="nav" #content [root]="rootPage"></ion-nav>
In order to use Menu, you must specify a reference to the content element that Menu should listen on for drag events, using the content
property. This is telling the menu which content the menu is attached to, so it knows which element to move over, and to respond to drag events. Note that a menu is a sibling to its content.
By adding the #content
to <ion-nav>
we are creating a local variable called content which references this component. We are then using this variable to set the <ion-nav>
as the content property of the <ion-menu>
through the following piece of code: [content]="content"
.
With the [root]="rootPage"
we are setting the root property to the rootPage variable which we'll later define in the app.js file.
Next, let's move on to this piece of code:
<ion-list>
<button ion-item *ngFor="#p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
So, within the <ion-content>
, which is obviously the content of our menu, we are declaring a list of buttons for each page within the pages variable that we'll define inside the app.js file as well.
ngFor
will create a button for each page we defined in the constructor earlier (like ng-repeat
in Angular 1), the * syntax means it will create an embedded template for each of the pages (it won’t render out the exact code we have above to the DOM, instead it will use the templates created), and by using #p
we are able to keep a reference to a specific page, which we pass into the openPage
function (defined in app.js file) when the button is clicked.
Next, let's move on to the app.js file.
After I added the menu to app.js my code looks like this:
import 'es6-shim';
import {App, Platform, IonicApp, MenuController} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Page1} from './pages/page1/page1';
import {Page2} from './pages/page2/page2';
import {Page3} from './pages/page3/page3';
@App({
//template: '<ion-nav [root]="rootPage"></ion-nav>',
templateUrl: 'build/app.html',
config: {} // http://ionicframework.com/docs/v2/api/config/Config/
})
export class MyApp {
//this gets injected into constructor below, it's the order that matters
static get parameters() {
return [[IonicApp], [Platform], [MenuController]];
}
constructor(app, platform, menu) {
this.app = app;
this.platform = platform;
this.menu = menu;
this.initializeApp();
// set our app's pages
this.pages = [
{ title: 'Page 1', component: Page1 },
{ title: 'Page 2', component: Page2 },
{ title: 'Page 3', component: Page3 }
];
this.rootPage = Page1;
}
initializeApp() {
this.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();
});
}
openPage(page) {
// close the menu when clicking a link from the menu
this.menu.close();
// navigate to the new page if it is not the current page
let nav = this.app.getComponent('nav');
nav.setRoot(page.component);
}
}
Firstly, I needed to import some components from the ionic-angular library. The new components that I imported are:
- IonicApp - provides some information about the app, and also keeps track of all the components within the application (as well as allowing us to select specific components)
- Platform - provides information about the platform that the app is running on (e.g. width, height, landscape, portrait etc.), in this case we’re using it to detect when the app is ready
- MenuController - allows us to create and manage a sliding menu
Next I changed the parameters()
method to include these new services.
static get parameters() {
return [[IonicApp], [Platform], [MenuController]];
}
This function is what injects the services into the MyApp's constructor, and the order of the services listed within this function is very important. This order directly corresponds to the order of parameters within the constructor below:
constructor(app, platform, menu) {
//code omitted for brevity
}
This means that the app
variable will be injected with IonicApp service, platform
with Platform service, and menu
with MenuController service. The names of the constructor parameters is not important in this context, only the order.
Next, within the @App decorator I changed the inline template
to use the templateUrl
pointing to the app.html file I previously created. Note that @App decorator marks the MyApp component as the root component of the entire app. You'll also notice later on that page component have the @Page decorator.
Finally, within the constructor I assigned the appropriate variables, set the rootPage
which is the first page that gets shown when the app is run, and populated the pages
array, which gets iterated over in the app.html template to build the buttons for our menu.
Lastly, I created the openPage(page)
method which gets called from the Menu buttons to hide the menu and switch over to the selected page. Here we see a new function called getComponent
, this is provided by the IonicApp service – it takes in an id and will return the component in the app with that id. In this case we are using it to grab the menu component and close it whenever a page is selected, and also to grab the nav component so that we can change the rootPage
(by calling setRoot
). We usually use NavController to manage navigation in the application, but this is not available in the root component, so we have to grab the nav component manually with IonicApp instead.
You could run the code written so far and open the Menu by swiping from left to right. The menu is fully functional, however, there is no Menu icon anywhere on the screen, which is not good.
To add the menu button I added the following piece of code to all of the page templates (page1.html, page2.html, page3.html).
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
Below you can see how the full HTML template for Tab 3 looks like when I added the above code to the page3.html file:
<ion-navbar *navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>
Tab 3
</ion-title>
</ion-navbar>
<ion-content class="page3">
</ion-content>
In the end it didn't took me a long time to add the similar menu I had in out-of-the-box template for Native Android to my Ionic app. The whole processes was pretty simple and straightforward, and I can already see how easy it will be to extend the menu's look and functionality. You can see the end result below.
I have to mention Josh Morony and his amazing blog post which helped me a lot with the implementation of this menu, and not only that, it helped me quickly understand some of the Ionic2 and Angular2 key implementation details.
Other references:
- Android
- Getting Started
- Project Structure
- Gradle
- Menu
- Theming
- Login Screen
- Menu & Navigation
- Importing Library From GitHub
- Creating Reusable Layouts
- Adding New Icons
- Profile Screen
- Chat Screen
- Contacts Screen
- Pending Invites Screen
- Settings Screen
- Add Library Dependency
- Discover Users Screen
- Splash Screen
- Auth0
- Authentication Logic
- Profile Screen Logic
- Send Feedback
- Authenticated to Firebase via Auth0
- Saving User Info to Firebase
- Storing User Connection Info to Firebase
- Calculating Distance Between Users
- Chat Logic
- Handling Device Rotation
- Android Other
- Ionic
- Getting Started
- Project Structure
- Menu
- Theming
- Login Screen
- Adding Images
- Creating Reusable Layouts
- Adding New Icons
- Profile Screen
- Contact Screen
- Elastic Textarea
- Chat Bubble
- Chat Screen
- Contacts Screen
- Pending Invites Screen
- Settings Screen
- Discover Users Screen
- Splash Screen
- Animations
- Auth0
- Storing User Data
- Profile Screen Logic
- Send Feedback
- Update to Ionic RC0
- Reimplemented Auth0 with Ionic RC0
- Authenticated to Firebase via Auth0
- Saving User Info to Firebase
- Storing User Connection Info to Firebase
- Calculating Distance Between Users
- Chat Logic
- Handling Device Rotation
- Ionic Other
- Version Updating
- Cordova
- Other
- Messaging