Where to place an IonMenu (in the code)

short version:
I would like to have the same IonMenu in all my IonPages. Is there a way to move the menu above the pages, maybe next to the routing?

How do I set this up properly?

Detailed version:

My app has an IonMenu that is used to navigate between routes. It has a list of entries, each of them an IonItem that links to a route like ‘/home’, ‘/config’, etc.

Here’s a mock up of the current state

<router>
  <route path="/home">
    <lots of layout code for the menu>
    <page>
  </route>
  <route path="/about">
    <same menu code again>
    <another page>
  </route>
  ...
</router>

So this is horrible code duplication, the same code for the menu is duplicated on each page.

As far as I can see, there would be two solutions:

  • make a custom component for the menu. Then it’s only a single tag (and I would have to pass in the content-id via props)
  • move the menu up, above the router

I would prefer the second solution. Because the menu really is the same everywhere, it doesn’t depend on the routes. So I think it should be specified outside of the routing, as a sibling to the router. That would mirror the structure of the UI.

As far as I understand, there are the following requirements:

  • The IonMenu needs to be given a contentId. I think this should be IonRouterOutlet. The contentId specifies an element on which to listen for swipe actions. And I want that element to be the output of the routing.
  • There needs to be a toolbar with the IonMenuButton. I think this should go into an IonHeader. Intuitively I would place this header next to the IonMenu, as another sibling to the router. But the documentation says that: It’s important to note that ion-header needs to be the one of the three root elements of a page. And I’ve got the impression that they mean an actual literal IonPage here.
  • Every Route must be an IonPage and IonPages must not be nested inside of each other.

I tried placing the IonHeader next to the routing, but then the pages and the header overlap each other. This doesn’t seem to work. So I moved the header inside of the IonPage and came up with the following code (simplified to provide a minimal example):

App.tsx:

 <IonApp>
    <IonMenu side="start" contentId="main-content">
      <IonList>
        <IonItem routerLink="/home">
          <IonLabel>home</IonLabel>
        </IonItem>
        <IonItem routerLink="/config">
          <IonLabel>config</IonLabel>
        </IonItem>
      </IonList>
    </IonMenu>

      <IonReactRouter>
        <IonRouterOutlet id='main-content'>
          <Route path="/home" component={Home} exact={true} />
          <Route path="/config" component={Config} exact={true} />
          <Route exact path="/" render={() => <Redirect to="/home" />} />
        </IonRouterOutlet>
      </IonReactRouter>
  </IonApp>

Home.tsx:

    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonMenuButton></IonMenuButton>
          </IonButtons>
          <IonTitle>Routing Menu</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <IonButton routerLink="/config">To the config!</IonButton>
      </IonContent>
    </IonPage>

Config.tsx (this one without the menubar)

      <IonPage>
        <IonContent>
          <IonButton routerLink='/home'>To the home!</IonButton>
        </IonContent>
      </IonPage>

This code doesn’t work. If I transition between routes with the buttons, they are changed properly, with a small animation. But if the menu is used for navigation, the page flickers and seems to re-render completely. There is no transition animation between the pages.

What is the correct way to do this?

Here is a small video of the behaviour.
When using buttons for routing, the animations look ok.
With the menu it somehow reloads.

ezgif-3-ceb71c97272f

Take a look at the menu starter project for a proper menu structure.

ionic start myApp menu

A menu should exist at a root point, and not be included in multiple pages.

1 Like

Sounds good, but there is no such starter template.

ionic start menuApp menu

Oh but there is sidemenu. And that sample looks great.

I think that fixes it. Thanks !