Stack Based Navigation (Push/Pop) with Ionic Web Components

Stack Based Navigation (Push/Pop) with Ionic Web Components

Follow Josh Morony on

Learn Ionic with Josh ☕

Hey, I hope you enjoy the article.

If you want a weekly update with my newest content, access to the blog's bonus content, or you want to sign up for one of my free beginner or advanced email courses just enter your details here or in the form below.

The introduction of Stencil and Ionic 4.x has led to a much larger focus on using routes for navigation. In the past, Ionic applications relied mostly on using a navigation stack with a push/pop style of navigation. If you are unfamiliar with how this style of navigation works, I would recommend reading one of my previous tutorials on navigation in Ionic/Angular.

This push/pop style of navigation makes a lot of sense for mobile applications. However, since Ionic is increasing support for Progressive Web Applications, and generally just supplying generic web components that can run anywhere on the web, it makes sense to support URL based routing which makes more sense in a web environment.

If you take a look at the Ionic PWA Toolkit, which is a sort of best practices starter template for building mobile applications with Ionic and Stencil, you will see that there are routes for navigation set up like this:

<ion-app>
    <main>
      <ion-router useHash={false}>
        <ion-route url='/' component='app-home'></ion-route>
        <ion-route url='/profile/:name' component='app-profile'></ion-route>

        <ion-nav></ion-nav>
      </ion-router>
    </main>
  </ion-app>

In order to navigate to a particular page, it is just a matter of activating the correct URL. If we wanted to go to the profile page, we would just need to navigate to:

http://localhost:3333/profile/whatever

This is different to what would typically be done in the past, where we would navigate by calling a particular function and triggering code like this:

this.navCtrl.push('MyProfilePage');

Even though routing with URLs is the default supplied in the starter project, and it probably is a good idea to use it if you plan on releasing your application for the web, you can still use this stack-based navigation if you want to. Perhaps you just intend to build your Ionic project as a native mobile application and don’t need to worry about URLs… or maybe you just really like push/pop style navigation.

In this tutorial, we are going to cover how to use push/pop style navigation in an Ionic/Stencil project. We will be using the Ionic PWA Toolkit as a base, and then we will remove the URL routing from that and add in push/pop navigation. Although this example is specifically using Stencil, these concepts will apply no matter where you are using Ionic’s web components. However, keep in mind that these concepts likely won’t apply to Ionic/Angular applications since we will have the ionic-angular package to help with navigation.

IMPORTANT: We are using an early version of the Ionic 4.x components. Ionic 4 has not officially been released yet. You should not use this in a production application yet (unless you are some kind of web dev maverick).

Generate a New Ionic/Stencil Project

We are going to create a new Ionic/Stencil project by cloning the Ionic PWA Toolkit repo. Just run the following commands to get your project up and running:

git clone https://github.com/ionic-team/ionic-pwa-toolkit.git ionic-push-pop
cd ionic-push-pop
git remote rm origin
npm install

Once everything has finished installing, you can run your project throughout development with:

npm run dev

Setting up Push/Pop Navigation in an Ionic/Stencil Project

All we need to do to set up push/pop navigation in this project is to modify the template of the root component. This is where the routes are set up currently, but we want to remove those and just rely on <ion-nav> instead.

Modify the render function in src/components/my-app/my-app.tsx to reflect the following:

render() {
    return (
      <ion-app>
        <ion-nav root="app-home"></ion-nav>
      </ion-app>
    );
  }

It is important to supply a root component to <ion-nav> here, which will be the default component that is displayed and also the root of your navigation stack.

Pushing and Popping

Now we are going to take a look at how to push and pop pages. In case you are unfamiliar and haven’t read the tutorial I linked earler, pushing will add a new page onto the navigation stack (making it the current page), and popping will remove the most recent page from the navigation stack (making the previous page the new current page).

There is actually a couple of ways that we can do this. The cool thing about how these web components are set up is that you don’t even need to write any functions or logic to navigate between pages, you can just use these web components:

  • <ion-nav-push>
  • <ion-nav-pop>
  • <ion-nav-set-root>

We are going to modify the home page to demonstrate this.

Modify the render function src/components/app-home/app-home.tsx to reflect the following:

render() {
    return (
      <ion-page>
        <ion-header>
          <ion-toolbar color='primary'>
            <ion-title>Ionic PWA Toolkit</ion-title>
          </ion-toolbar>
        </ion-header>

        <ion-content>
          <p>
            Welcome to the Ionic PWA Toolkit.
            You can use this starter to build entire PWAs all with
            web components using Stencil and ionic/core! Check out the readme for everything that comes in this starter out of the box and
            Check out our docs on <a href='https://stenciljs.com'>stenciljs.com</a> to get started.
          </p>

          <ion-nav-push component="app-profile">
            <ion-button>Push Profile Page</ion-button>
          </ion-nav-push>

          <ion-nav-set-root component="app-profile">
            <ion-button>Make Profile Page Root Component</ion-button>
          </ion-nav-set-root>

        </ion-content>
      </ion-page>
    );
  }

If we want to push our profile page, all we need to do is this:

<ion-nav-push component="app-profile">
    <ion-button>Push Profile Page</ion-button>
</ion-nav-push>

Now when this button is clicked, it will push the app-profile component. If we instead wanted to make the profile component the new root page, we could do that by using:

<ion-nav-set-root component="app-profile">
    <ion-button>Make Profile Page Root Component</ion-button>
</ion-nav-set-root>

Now let’s see how we would pop back to the home page after pushing to the profile page.

Modify the render function in src/components/app-profile/app-profile.tsx to reflect the following:

render() {
    return (
      <ion-page>
        <ion-header>
          <ion-toolbar color='primary'>
            <ion-buttons slot="start">
              <ion-back-button text="Home"></ion-back-button>
            </ion-buttons>

            <ion-title>Ionic PWA Toolkit</ion-title>
          </ion-toolbar>
        </ion-header>

        <ion-content>

            <ion-nav-pop>
              <ion-button>Pop</ion-button>
            </ion-nav-pop>

            <p>Pop will only work if this page was pushed, not if it was set as the new root component</p>

        </ion-content>
      </ion-page>
    );
  }

All we need to do to pop off the current view is:

<ion-nav-pop>
    <ion-button>Pop</ion-button>
</ion-nav-pop>

However, keep in mind that if you arrived on the profile page by setting the profile page as the “root” page, then you won’t be able to “pop” back to the previous page (because the profile page is now the base of the stack and there is nothing left to pop back to).

Navigating Programmatically

Being able to use the web components directly in the HTML to trigger page navigation is pretty cool, but sometimes we will also want to just navigate programmatically as well. This is really simple to do. All we need to do is grab a reference to the <ion-nav> and then call the appropriate method on it (e.g. push or pop). Let’s take a look at an example.

Modify src/components/app-home/app-home.tsx to reflect the following:

import { Component } from '@stencil/core';

const nav = document.querySelector('ion-nav');

@Component({
  tag: 'app-home',
  styleUrl: 'app-home.scss'
})
export class AppHome {

  goToProfile(){
    nav.push('app-profile');
  }

  render() {
    return (
      <ion-page>
        <ion-header>
          <ion-toolbar color='primary'>
            <ion-title>Ionic PWA Toolkit</ion-title>
          </ion-toolbar>
        </ion-header>

        <ion-content>
          <p>
            Welcome to the Ionic PWA Toolkit.
            You can use this starter to build entire PWAs all with
            web components using Stencil and ionic/core! Check out the readme for everything that comes in this starter out of the box and
            Check out our docs on <a href='https://stenciljs.com'>stenciljs.com</a> to get started.
          </p>

          <ion-nav-push component="app-profile">
            <ion-button>Push Profile Page</ion-button>
          </ion-nav-push>

          <ion-nav-set-root component="app-profile">
            <ion-button>Make Profile Page Root Component</ion-button>
          </ion-nav-set-root>

          <ion-button onClick={() => this.goToProfile()}>Push Profile Page with Function</ion-button>

        </ion-content>
      </ion-page>
    );
  }
}

We’ve set up a button that will trigger the goToProfile function. This function just calls the push method on nav which is a constant variable we set up at the top of this component. All we need to do is supply it with the name of the component that we want to push.

Summary

If you have a background with Ionic/Angular, then this style of navigation will likely feel pretty comfortable to you. In terms of which approach you should use, I would say in general to use the URL route approach if you are going to be deploying your application to the web, and push/pop style navigation if it is just going to be deployed as a native mobile application. In the end, there is no hard and fast rules – use what works best for you.

If you enjoyed this article, feel free to share it with your friends ☝

Check out my latest videos: