Ionic By Component: Navigation

02 January 2017 / By Sani
Navigation is one the key areas that Ionic significantly improved on for Ionic 2. In Ionic 2, we have a new shiny Navigation mechanism that has some powerful features which enable us to do some great things. In this post, we will first look at some of the difficulties the Navigation system in Ionic V1 had. We will then look at the new Navigation system available in Ionic V2 and learn to use these features.

Navigation In V1

Ionic V1 had a navigation system based on the UI-Router in Angular 1x. This navigation system in Ionic 1x got the simple things done, but it was not powerful enough to enable us to do some more powerful things. Listed below are some of the shortcomings that were either impossible or difficult to achieve with the old navigation system.
  1. Navigate Between A Single Page Concurrently
  2. Coupled To The URL Bar
  3. Modals Were 2nd Class Navigation Citizens
  4. Unable To Fully Control Navigation History
  5. Difficult To Deep Link

Navigation In V2

The navigation system in Ionic 2 is a completely rethought effort and custom routing effort. It is also not based on the current routeing system made available by Angular. I honestly believe in my opinion that it is a much simpler system in comparison to the routeing provided by Angular. It also gives us different Lifecycle events which you can learn about by reading IONIC BY COMPONENT: PAGE LIFECYCLE. Let's have a look at the different features of the navigation system in Ionic 2.
Ionic 2 Navigation Components
  • NavController
  • NavParams
  • NavPop
  • NavPush
  • Nav
  • NavBar
We will only be covering the components in bold and would be leaving out the Nav & Navbar components in this tutorial as they are part of a different scope. Now let's dive into each component and learn about what each lets us do.

NavController

The NavController controller is a service that is used to navigate between pages. Each page in Ionic is an Angular @Component and to navigate between a page all we need to do is have a reference to the Component we want to navigate to. Let's assume that we have a @Component called FirstPage & another @Component called SecondPage.
FirstPage @Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { SecondPage } from '../second/second';

@Component({
  selector: 'page-first',
  templateUrl: 'first.html'
})
export class FirstPage {

  constructor(private navCtrl: NavController) {}

  goToSecondPage(){
    this.navCtrl.push(SecondPage);
  }

}
SecondPage @Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-second',
  templateUrl: 'second.html'
})
export class SecondPage {

  constructor(private navCtrl: NavController) {}

  goBackToPreviousPage(){
    this.navCtrl.pop();
  }

}

The code provided above shows how we can use the NavController to move from one page to another. The NavController has 2 functions, push() & pop() that let us navigate & go back between pages respectively.
NavController push()
The push() function allows us to move between pages & can take 3 possible parameters. If we examine the code for our FirstPage @Component, we can see that the first thing we did on line 2 & 3 is to import our NavController and also import the @Component we want to navigate to which in this case is the SecondPage @Component.
import { NavController } from 'ionic-angular';
import { SecondPage } from '../second/second';
We then injected the NavController instance as navCtrl on line 11 to make it available as a property within our @Component. Line 13-15 shows how we created a function goToSecondPage() within which we call the NavController instance on line 14 and use its push() function. We pass the SecondPage @Component we imported on line 2 as a parameter. The piece of code on line 14 tells the NavController to navigate to the @Component passed, and it's as simple as that to navigate between pages in Ionic.
constructor(private navCtrl: NavController) {}

  goToSecondPage(){
    this.navCtrl.push(SecondPage);
  }
No extra setup required and also no URL path to be passed as well. All we need to know is the @Component we want to go to, and this can also be the very same @Component we are in which means we can pass FirstPage @Component if we wished, and the navigation would still work flawlessly. We can also take a look at the SecondPage @Component code and have a closer look at the code on line 13.
    this.navCtrl.pop();
We can see a pop() function that the NavController exposes. This pop() function does the opposite of the push() function but it doesn't require a @Component instance to be passed. All this code will simply do is go back to the previous page and the greatest thing about it is that we do not need to know what @Component the previous page is as the NavController has all that details and will remove our current Page from the stack and take us back automatically. You can read more about the the NavController on the NavController Ionic Docs Page.

NavParams

Majority of the times you navigate, you would ideally want to be able to pass parameters. This is also very simple to do with the new navigation system. Ionic provides the NavParams service which enables us to obtain passed parameters. Let us modify our sample from the previous examples with the FirstPage & SecondPage @Components and see what navigating with parameters looks like.
FirstPage @Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { SecondPage } from '../second/second';

@Component({
  selector: 'page-first',
  templateUrl: 'first.html'
})
export class FirstPage {

  constructor(private navCtrl: NavController) {}

  goToSecondPage(){
    this.navCtrl.push(SecondPage, {
      firstParamName: 'firstParamValue',
      secondParamName: 'secondParamvalue'
    });
  }

}
SecondPage @Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';

@Component({
  selector: 'page-second',
  templateUrl: 'second.html'
})
export class SecondPage {
  private firstParam;
  private secondParam;
  private allParams;

  constructor(private navCtrl: NavController, private navParams: NavParams) {
    this.firstParam = this.navParams.get('firstParamName');
    this.firstParam = this.navParams.get('secondParamName');
    this.allParams = this.navParams.data;

  }

  goBackToPreviousPage(){
    this.navCtrl.pop();
  }

}

Let's start by having a look at lines 14-17 of our new code for the FirstPage @Component. We can see that we passed a second parameter, which is a key/value object. This object is what we use to specify parameters we want to pass to the next @Component we are navigating to.
   this.navCtrl.push(SecondPage, {
      firstParamName: 'firstParamValue',
      secondParamName: 'secondParamvalue'
    });
In our SecondPage @Component, we first import the NavParams service into our project.
import { NavController, NavParams } from 'ionic-angular';
We then ensure that we have the NavParams injected in our constructor and then retrieve the parameters available to us. These can be seen between lines 13-18.
constructor(private navCtrl: NavController, private navParams: NavParams) {
    this.firstParam = this.navParams.get('firstParamName');
    this.firstParam = this.navParams.get('secondParamName');
    this.allParams = this.navParams.data;

  }
It helps to know the name of the parameters available to us as this would normally be the case. There will also be cases like this one where we pass multiple parameters and want to retrieve all of them at once. Line 16 show just how we can achieve this very feat via the data property that the NavParams service has.
    this.allParams = this.navParams.data;
This data property allows us to retrieve all parameters available. It's totally up to you to decide which method you prefer to use when retrieving parameters as both work very well. NavParams Official Docs Page

NavPush & NavPop

The NavPush & NavPop are used to declaratively implement the NavController's push() & pop() functions. This means you can navigate from your HTML templates directly. The NavPush & NavPop might seem like a duplicate feature but they are actually a pretty smart set of features. So far from previous code in this post, we have had to create a function that calls our navigation code. However, with the NavPush & NavPop, we can bind to any HTML element of our choosing and just pass the necessary parameters needed. To showcase this feature, we will be using the templates of our FirstPage & SecondPage @Components.
First Page @Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { SecondPage } from '../second/second';

@Component({
  selector: 'page-first',
  templateUrl: 'first.html'
})
export class FirstPage {
  public secondPage = SecondPage;
  public paramsForSecondPage = {
      firstParamName: 'firstParamValue',
      secondParamName: 'secondParamvalue'
    };

  constructor(private navCtrl: NavController) {}

  goToSecondPage(){
    this.navCtrl.push(SecondPage, {
      firstParamName: 'firstParamValue',
      secondParamName: 'secondParamvalue'
    });
  }

}
FirstPage HTML Template
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<ion-header>

  <ion-navbar>
    <ion-title>First Page</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>

  <button ion-button (click)="goToSecondPage()">Go To Second Page</button>
  <button ion-button [navPush]="secondPage">Go To Second Page</button>

</ion-content>

If you pay close attention to the HTML template of FirstPage, you will see that on line 12 & 13 we have 2 button components that you will see both the NavController & NavPush implementations for navigating to the SecondPage @Component. Line 12 on the FirstPage HTML template shows how we used the goToSecondPage() function we created on line 18 of the FirstPage @Component code.
  <button ion-button (click)="goToSecondPage()">Go To Second Page</button>
  <button ion-button [navPush]="secondPage" [navParams]="paramsForSecondPage">Go To Second Page</button>
You can also see that the [navPush] is a property being bound and it is being passed a parameter secondPage. We will also see that another property [navParams] takes in a parameter "paramsForSecondPage".
  public secondPage = SecondPage;
  public paramsForSecondPage = {
      firstParamName: 'firstParamValue',
      secondParamName: 'secondParamvalue'
    };
From the @Component code for the FirstPage HTML, we can see that the "secondPage" parameter we bind to the [navPush] property and the "paramsForSecondPage" parameter we bind to the [navParam] properly are provided in on lines 10-14 of the FirstPage @Component code. The "secondPage" parameter is actually a reference to the SecondPage @Component , while the "paramsForSecondPage" is a reference to an object which we are using as navigation parameters. You can see how similar this method is a bit more declarative than the NavController method.

NavPop

The NavPop is the opposite of the NavPush and is used to navigate back to the previous page.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<ion-header>

  <ion-navbar>
    <ion-title>Second Page</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>

  <button ion-button (click)="goBackToPreviousPage()">Go Back To Previous Page</button>
  <button ion-button navPop>Go Back To Previous Page</button>

</ion-content>
Lines 12 & 13 show how we navigate back both with the NavController method and the navPop method. The navPop method on line 13 shows how we didn't need to use a created function and bind directly to any HTML element. NavPush Official Docs Page NavPop Official Docs Page
Advice On NavPush & NavPop
As a rule of thumb I always advise that you use the [navPush] & navPop feature for your navigation especially the navPop for simple navigation actions. This is because the navPop & [navPush] make your code more declarative and save you lines of code in many cases. You should only use the NavController method when you need to access the navigation mechanism by code or need to perform some internal actions before of after a specific navigation action is executed.

Roundup

As seen in this post the new navigation mechanism is very mature and allows us to do a lot of new things in Ionic. Be sure to read IONIC BY COMPONENT: PAGE LIFECYCLE which details the lifecycle event of the Ionic of an Ionic Page. Stay tuned for more posts in this series and be sure to share this post if you enjoyed. Also feel free to talk about or ask about anything in the comments section below.  
  • Prince Oluwasegun Abisagbo

    this is a great post and makes me excited about Ionic/Angular 2…

    Cant wait to try it out

  • Samuel Adekanmbi

    Nice post

  • John Christian Lønningdal

    Seems there is a bug in ionic2 where you shouldnt use a selector for @Component. Having some serious issues with ionic2 where it feels like the nav just bombs out after some use and the whole app stops responding to clicks.

    https://github.com/driftyco/ionic/issues/7979#issuecomment-244882983

  • Yusuf Adeyemo

    Nice one bro. This is a Good read

  • supriya chauhan

    I am getting error, while navigating page from one to another using show(). I am well using the code it is navigating the next page but the next page is displayed with the error shown below in attachement. Please take a look.

    https://uploads.disquscdn.com/images/00edabade6af32d9ce72aee97a2bbe115d2f1c5f9a3eb35c5dbfd02ebb025475.png

  • Jeremy Flowers

    Hi Sani. I’ve noticed with @IonicPage and lazy loading, you would call push with a string like so this.navCtrl.push(‘secondPage’). Would your line 13 work if you quote it like this (navPush)=”‘secondPage'” if page was annotated and lazy loadable?

  • great and composite post.

  • Great post!