In this article, we are going to learn about the steps to integrate the side menu using the 'ion-menu' component in the Ionic&Vue application.
Create A Master Layout:
'ion-menu' Component:
Using the 'ion-menu' component we can develop a verticle side menu for our mobile ionic application. The menu should be rendered as a sibling element to the root content element. Mostly the root content element in our Ionic&Vue application is 'ion-router-outlet', so our menu element should be the sibling to it. So to operate on the menu component we have to use the 'menucontroller' that loads from the '@ionic/vue'. The key terms we need to remember while implementing the 'ion-menu' component:
menucontroller: The 'menucontroller' helps to operate on our menu like opening and closing of the menu. It's not ideal to use multiple menus in the application but ionic supports to render multiple menus so to open them from anywhere of entire application it is effortless by using 'menucontroller' methods like 'open' and 'close' by sending 'menu-id' value as an input parameter to operate on the particular menu.
menu-id: The 'menu-id' is like a name to the element whose value will be used by methods like 'open' and 'close' of the 'menucontroller'. It is also like a unique identifier.
content-id: The 'content-id' value should match with our menu element sibling root element 'id' value. Mostly this should be the 'id' value of the 'ion-router-outlet'.
side: The 'side' attribute defines that the menu should render which side.
open and close: From the names, we can understand those methods are used to open and close the menu.
Create A Sample Ionic&Vue Application:
Let's begin coding by creating a sample Ionic&Vue application.
Run the below command to setup ionic CLI.
Run the below command to setup ionic CLI.
Command to install latest Ionic CLI:
npm install -g @ionic/cli@latest
Now run the below command to create the Ionic&Vue application.
Command to create Ionic Vue application
ionic start your_app_name blank --type vue
TypeScript Or Javascript:
By default Ionic sample created with the support of TypeScript in any library like angular, react, and vue. Typescript can be chosen to develop our application. But in the case of Vue most of the developers or preferred to choose javascript syntax instead of Typescript for application development. So to make our Ionic Vue application use javascript we need to remove few Typescript references, so follow the below steps.
- Remove TypeScript dependencies.
command to unistall the typescript dependencies
npm uninstall --save typescript @types/jest @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript @vue/eslint-config-typescript
- We need to change the file extensions from ".ts" to ".js", we mostly have 2 '.ts files' like 'main.ts' and 'router/index.ts'.
- In the '.eslintrc.js' file needs to remove the '@vue/typescript/recommended' from the 'extends' array property and next need to remove the @typescript-eslint/no-explicit-any': 'off' property from the rules object.
- Now remove the 'Array<RouteRecordRaw>' type in 'router/index.js'.
- Delete the 'shims-vue.d.ts' file.
- Remove the 'lang="ts"' attribute on script tag in our '.vue' files like 'App.vue' and 'view/Home.vue'.
Create Vue Page Components:
Let's first delete the 'src/views' folder and files inside of it.
Now in our sample let's create 2 pages, so that we can navigate them using the menu once we integrate it.
Let's create a page vue component like 'Home.vue'.
src/pages/Home.vue:
<template> <ion-page> <ion-header> <ion-toolbar> <ion-title>Home Page</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-button expand="full">Open Menu</ion-button> </ion-content> </ion-page> </template> <script> import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButton, } from "@ionic/vue"; export default { components:{ IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButton } }; </script>
- Here we simply create an Ionic&Vue page using the ionic components that are loaded from the '@ionic/vue' library. Here we added the button 'Open Menu' which will write logic to open the menu later.
Now configure the routing for our 2 new pages.
src/router/index.js:
import Home from '../pages/Home.vue'; import About from '../pages/About.vue'; const routes = [ { path: '/', redirect: '/home' }, { path: '/home', component: Home }, { path: '/about', component: About } ]
Create Menu Vue Component:
The 'ion-menu' component has root child components like 'ion-header' and 'ion-content' which looks similar to the 'ion-page'.
Let's implement our menu vue component and add our 2 pages as its menu items.
src/components/Menu.vue:
<template> <ion-menu menu-id="app-menu" content-id="main-content"> <ion-header> <ion-toolbar> <ion-title>Welcome!</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <ion-item> <ion-label>Home</ion-label> </ion-item> <ion-item> <ion-label>About</ion-label> </ion-item> </ion-list> </ion-content> </ion-menu> </template> <script> import { IonMenu,IonHeader,IonContent,IonToolbar,IonTitle,IonItem,IonList,IonLabel, } from "@ionic/vue"; export default { components: { IonMenu,IonHeader,IonContent,IonToolbar,IonTitle,IonItem,IonList,IonLabel, }, }; </script>
- (Line: 2) The 'menu-id' attribute value is a unique identifier of our menu. The 'content-id' attribute value must match with the 'id' value of our menu sibling element(mostly sibling element will be 'ion-router-outlet').
- Here we rendered our 'ion-menu' component that consists of root children components like 'ion-header' and 'ion-content'. We also added our pages as menu items.
Render Menu Component To A Root Sibling:
Now we need to render our menu element to the root element that is the area content going to use our menu. The most preferred root element will be the 'ion-router-outlet'. That means all the pages or entire our application will have control over our menu. Our menu component 'content-id' value should match with the 'id' value of our root element(mostly ion-router-outlet).
src/App.vue:
<template> <ion-app> <Menu></Menu> <ion-router-outlet id="main-content"/> </ion-app> </template> <script> import { IonApp, IonRouterOutlet } from '@ionic/vue'; import { defineComponent } from 'vue'; import Menu from './components/Menu.vue'; export default defineComponent({ name: 'App', components: { IonApp, IonRouterOutlet, Menu } }); </script>
- (Line: 3) Rendered our menu component to the sibling element 'ion-router-outlet'.
- (Line: 4) The 'id' value will be used as the value to the 'content-id' attribute value in the menu component. This represents that area under this element will have control over our menu.
- (Line: 11) Imported our 'Menu' component.
- (Line: 18) Register our 'Menu' component.
Open Menu Using 'menuController':
Using 'menuController' we can open our menu. So we have registered the 'show menu' button on all our pages. Now we are going to create a 'click' event for the button which will invoke the menu open method.
src/pages/Home.vue:
<template> <ion-content> <ion-button @click="openMenu()" expand="full">Open Menu</ion-button> </ion-content> </template> <!-- Code hidden for display purpose --> <script> import {menuController} from "@ionic/vue"; export default { methods:{ openMenu(){ menuController.open("app-menu") } } }; </script>
- Here we are using 'menuController.open' method to invoke the menu. Here we pass the 'menu-id' attribute value to the open method.
Menu Navigation And 'menuController' Close Method:
Now we need to implement logic to navigate between the pages on clicking menu item and then we need to close the menu as well using the 'close' method of the 'menuController'.
src/components/Menu.vue:
<template> <ion-menu menu-id="app-menu" content-id="main-content"> <ion-header> <ion-toolbar> <ion-title>Welcome!</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <ion-item button @click="menuNavigation('/home')"> <ion-label>Home</ion-label> </ion-item> <ion-item button @click="menuNavigation('/about')"> <ion-label>About</ion-label> </ion-item> </ion-list> </ion-content> </ion-menu> </template> <script> import { IonMenu,IonHeader,IonContent,IonToolbar,IonTitle,IonItem,IonList,IonLabel, menuController } from "@ionic/vue"; export default { components: { IonMenu,IonHeader,IonContent,IonToolbar,IonTitle,IonItem,IonList,IonLabel, }, methods:{ menuNavigation(url){ menuController.close("app-menu"); this.$router.push(url); } } }; </script>
- (Line: 10&13) Menu item click event registered with their respective URLs as the input parameter.
- (Line: 23) The 'menuController' that loads from the '@ionic/vue'.
- (Line: 30-33) Here using the 'close' method of the 'menuController' closing our menu and then navigating to the target page.
Create A Master Layout:
In general, for mobile application menu button will available at the header part of the application. But if you recall our pages we are creating individual header and content parts for each page so, in this scenario, a menu button needs to be added on both pages like 'Home.vue' and 'About.vue' which means duplication of code, so to avoid this issue most recommended is to create a 'Master Layout' where it contains header and footer part that will be shared by pages in our application.
src/components/MasterLayout.vue:
<template> <ion-page> <ion-header> <ion-toolbar> <ion-title>{{pageTitle}}</ion-title> </ion-toolbar> </ion-header> <ion-content> <slot></slot> </ion-content> </ion-page> </template> <script> import { IonPage, IonHeader, IonContent, IonTitle, IonToolbar } from '@ionic/vue'; export default { components:{ IonPage,IonHeader,IonContent,IonTitle,IonToolbar }, props:['pageTitle'] } </script>
- Here our 'MasterLayout' of our application is a build-up of ionic components like 'IonPage', 'IonHeader', 'IonToolbar','IonTitle'. Here the 'slot' element to render the content of our vue page component with respective of their routes.
src/main.js:
// code hidden for display purpose import MasterLayout from './components/MasterLayout.vue' const app = createApp(App) .use(IonicVue) .use(router); app.component('master-layout',MasterLayout);Now update our pages to use the 'MasterLayout' to share common content to every page.
src/pages/Home.vue:
<template> <master-layout pageTitle="Home Page"> <ion-button @click="openMenu()" expand="full">Open Menu</ion-button> </master-layout> </template> <script> import { menuController } from "@ionic/vue"; export default { methods: { openMenu() { menuController.open("app-menu"); }, }, }; </script>src/pages/About.vue:
<template> <master-layout pageTitle="About Page"> <ion-button @click="openMenu()" expand="full">Open Menu</ion-button> </master-layout> </template> <script> import { menuController } from "@ionic/vue"; export default { methods: { openMenu() { menuController.open("app-menu"); }, }, }; </script>
Add Menu Icon And Click Event To Open Menu:
Now in our 'MasterLayout', we are going to add a menu button with an icon and then we will register to click the callback method that contains logic to open our menu.
src/components/MasterLayout.vue:
<template> <ion-page> <ion-header> <ion-toolbar> <ion-buttons @click="openMenu()" slot="start"> <ion-icon :icon="menu" slot="start"></ion-icon> </ion-buttons> <ion-title>{{ pageTitle }}</ion-title> </ion-toolbar> </ion-header> <ion-content> <slot></slot> </ion-content> </ion-page> </template> <script> import { IonPage,IonHeader,IonContent,IonTitle,IonToolbar,IonButtons,IonIcon, menuController, } from "@ionic/vue"; import { menu } from "ionicons/icons"; export default { components: { IonPage,IonHeader,IonContent,IonTitle,IonToolbar,IonButtons,IonIcon, }, props: ["pageTitle"], data() { return { menu, }; }, methods: { openMenu() { menuController.open("app-menu"); }, }, }; </script>
- (Line: 5-7) The 'IonButtons' component rendered and registered click event with callback method 'openMenu'. Using 'IonIcon' component rendering the menu icon.
- (Line: 19) Imported 'menuController'.
- (Line: 21) Imported 'menu' icon.
- (Line: 27-31) Returning 'menu' as a data property.
- (Line: 33-35) Callback method 'openMenu' here using 'menuController' we open menu bypassing the 'menu-id' attribute value as input param.
src/pages/Home.vue:
<template> <master-layout pageTitle="Home Page"> <div>Welcome Home Page!</div> </master-layout> </template> <script> export default { }; </script>src/pages/About.vue:
<template> <master-layout pageTitle="About Page"> <div>Welcome About Page!</div> </master-layout> </template> <script> export default { }; </script>That's all about the steps to implement the menu in the Ionic&Vue application.
Support Me!
Buy Me A Coffee
PayPal Me
Wrapping Up:
Hopefully, I think this article delivered some useful information on integrating the side menu in the Ionic&Vue application. I love to have your feedback, suggestions, and better techniques in the comment section below.
Thank you!! The best resource I have found on Ion Menu with Vue.
ReplyDeleteVery nice, thanks!
ReplyDeleteWhat's the difference between this and the 'sidemenu' started?
Awesome tutorial, for some reason when I run this on the emulator or on an actual device the menu and title bar disappears
ReplyDelete