Basic navigation in Ionic

November 26, 2016, 1:00 pm Categories:

Categories

The old way - Ionic 1

** NOW UPDATED FOR IONIC 3 **

If you developed mobile apps using version 1 of the Ionic framework you're probably familiar with navigation based on state or URL routing, courtesy of Angular, like so:

.config(function($stateProvider, $urlRouterProvider)
{
    $stateProvider


   // Home 
   .state('index',
   {
      url             :   '/',
      templateUrl     :   'assets/templates/home.html',
      controller      :   'HomeController'
   })


   // Search
   .state('search-options',
   {
      url             :   '/search/options',
      templateUrl     :   'assets/templates/search-options.html',
      controller      :   'SearchOptionsController'
   });

   $urlRouterProvider.otherwise("/");

});

Looking at this now I feel a little nostalgic (it's kind of scary how quickly technologies and processes change don't you think?)

The latest iteration of the Ionic framework changes this approach to navigation completely...

Getting stacked with Ionic

With Ionic movement from one page of an app to the next is managed through the navigation stack (which you can envision as a stack of pages layered on top of one another with the current page being at the top).

Here's how it works:

  • When you navigate to a page you push that page onto the top of the stack
  • When you navigate from that page you pop it from the stack

This is accomplished using the NavController module which is automatically added to every page component generated with the Ionic CLI. This provides a number of methods that we can use to implement navigation within our Ionic apps.

We'll explore using one of these methods: push in a new app that we'll create using the Ionic CLI.

In your software console of choice (I.e. Terminal on Mac OS X, Command Prompt on Windows) run the following command:

ionic start blank simple-navigation

In the above console command we've generated a basic project named simple-navigation that uses a blank template.

We could have chosen tabs or sidemenu as our templates of choice but they implement navigation slightly differently (I cover these, along with further navigation related topics, in more depth in my book - Mastering Ionic: The Definitive Guide).

Now we need to change into the root of our newly generated project and generate an additional page that we can navigate to and from.

Implement the following commands in your console, line by line:

cd simple-navigation
ionic g page second

After running the above commands you should see a page directory structure that looks like the following:

Ionic project structure for a new mobile app

Now we have the basic foundation for our app already built let's start fleshing that out.

Implementing navigation

Open the simple-navigation/src/pages/home/home.ts file and change the existing code to the following:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  
   constructor(public navCtrl: NavController) {
    
   }


   navigationLink()
   {
      this.navCtrl.push('Second');
   } 

}

There are 3 important aspects of the above script that we need to be aware of:

  • We import the NavController module so we can access its methods for implementing navigation to other pages within our app
  • The constructor creates a public property of navCtrl which is used to reference the NavController module and its methods
  • Finally, we manually add a method named navigationLink (which will provide the functionality to navigate between the pages of our simple-navigation application)

The navigationLink method uses the built-in NavController module to "push" the Second page to the top of the navigation stack:

navigationLink()
{
   this.navCtrl.push('Second');
} 

When this method is triggered the supplied page (in the above example this is class name of the Second page component) will be "pushed" onto the navigation stack so that it becomes the current page being viewed.

In order to trigger this method we need to be able to call it from the HTML of our home page component.

Open the simple-navigation/src/pages/home/home.html file and change the existing markup to the following:

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <button
   ion-button
   color="primary"
   block
   (click)="navigationLink()">
     Go to page 2
  </button>
</ion-content>

The changes we've implemented are fairly minimal and simply consist of a button with a click event that, when triggered by the user, calls the navigationLink method from the component's class.

If you're not familiar with Ionic/Angular development you might be surprised should you try running this example now.

Rooting the Second page component module

If you try to preview the above in your desktop browser using ionic serve you'll most likely (until this is fixed in subsequent releases of the Ionic Framework) be greeted with the following error message:

second.module.ts, line: 10
           Property 'forChild' does not exist on type 'typeof IonicModule'.

      L9:  imports: [
     L10:    IonicModule.forChild(Second),
     L11:  ],

This might look a little daunting but it's actually quite simple to resolve.

The solution?

Open the simple-navigation/src/pages/second/second.module.ts file and change all references from IonicModule to IonicPageModule like so:

import { NgModule } from '@angular/core';
import { Second } from './second';
import { IonicPageModule } from 'ionic-angular';

@NgModule({
  declarations: [Second],
  imports: [
    IonicPageModule.forChild(Second)
  ],
  entryComponents: [
    Second
  ]
})
export class SecondModule { }

Save these changes and now, when you run the ionic serve command from your CLI, you should be greeted with the following screen instead:

Blank home page with navigation button

Which is a huge improvement on the last time we tried to preview the app in the browser!

Clicking on the button will allow the app to navigate to the second page:

Blank second page of an Ionic app

Notice how Ionic automatically adds a back button to the header bar of the second page?

Now that we can successfully navigate between pages using the NavController module let's look at how we can pass data from one page to the next.

Navigation parameters

We've used the NavController module to help initiate navigation within our app now we're going to enhance this by using the NavParams module to retrieve data passed between pages.

Firstly we need to set some data.

Start by opening your simple-navigation/src/pages/home/home.ts file and add the following block of code after the beginning of the HomePage class declaration like so:

export class HomePage {
   public params : any = {
      name: 'Ionic',
      message : 'hello world'
   };

This is just a simple key/value object that we'll use to pass data for the standard hello world example used in most tutorials - very original huh?

This params object will then need to be added as a second parameter to the push method of the NavController object like so:

navigationLink()
{
   this.navCtrl.push('Second', this.params);
} 

With those amendments made the simple-navigation/src/pages/home/home.ts file should now resemble the following:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
   public params : any = {
      name: 'Ionic',
      message : 'hello world'
   };
  
   constructor(public navCtrl: NavController) {
    
   }



   navigationLink()
   {
      this.navCtrl.push('Second', this.params);
   } 

}

Now you'll need to open the simple-navigation/src/pages/second/second.ts file and make the following changes:

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';


@Component({
  selector: 'page-second',
  templateUrl: 'second.html'
})
export class Second {
   public message : string;

   constructor(public navCtrl: NavController, 
               public params : NavParams) 
   {
      this.message = `${this.params.data.name} says ${this.params.data.message}`;
   }


   ionViewDidLoad() {
      console.log(`${this.params.data.name} says ${this.params.data.message}`);
   }

}

Here we've imported the NavParams module at the top of the script followed by defining a public property named message within the second page component class.

Within the class constructor this message property is then assigned a string value composed from values passed by the NavController module in the HomePage component (and retrieved using the NavParams data member):

this.message = `${this.params.data.name} says ${this.params.data.message}`;

Notice how we use template strings and interpolation to embed the name and message values from the parsed navigation data within the constructed string?

I love that particular TypeScript feature - so handy!

In the above example we use the data member of the NavParams class to access the object that was passed from the home page and, using dot notation syntax, drill down into that to access the name and message keys.

We could have used the get member of the NavParams class instead to individually access these values like so:

this.params.get('name');
this.params.get('message');

Either way is fine although I personally prefer accessing values using the data member instead.

We then use the ionViewDidLoad method which allows us to perform actions once the page has loaded - in this case rendering a simple console log to the browser with our recently constructed message.

In the simple-navigation/src/pages/second/second.html file make the following mark-up change:

<ion-header>
  <ion-navbar>
    <ion-title>second</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
   <p>{{ message }}</p>
</ion-content>

As the page template was a little bland, to say the least, we just want to spice things up a bit by rendering our message to the page as well as the browser console.

Save your work, run ionic serve and you should now be greeted with the following message when navigating to the second page:

Hello World example on second page of Ionic app

And that's how easy it is to implement navigation in the latest version of Ionic!

Summary

That concludes our look into implementing basic navigation within Ionic.

Thanks to a component based architecture and use of the NavController and NavParams modules navigation has been greatly simplified in the latest iteration of the Ionic framework.

The set-up and implementation is much more streamlined with data able to be passed between pages on a component by component basis which is an improvement on the Ionic 1 way of doing things (even if I did personally like that).

For more in-depth information on Ionic navigation, including managing the root page and implementing lifecycle events, download my e-book: Mastering Ionic.

Tags

Categories

Post a comment

All comments are welcome and the rules are simple - be nice and do NOT engage in trolling, spamming, abusiveness or illegal behaviour. If you fail to observe these rules you will be permanently banned from being able to comment.

Top