Adding multiple pages using tabs

This section will explain how to work with the Ionic tab interface and expand it for other cases. The example used is very basic with three tabs and some sample Ionic components in each tab. This is a very common structure that you will find in many apps. You will learn how Ionic 2 structures the tab interface and how it translates to individual folders and files.

In this example, you will build three tabs, as follows:

  • Showing a simple text-only page to explain where to fit the components
  • Showing a sign up form
  • Showing a horizontal slider box

Although the app is very straightforward, it will teach you a lot of key concepts in Angular 2 and Ionic 2. Some of them are the component decorators, theme and the TypeScript compiler process.

Here is a screenshot of the app where the middle tab is selected:

Adding multiple pages using tabs

Getting ready

Since this is your first app being built from scratch, you need to ensure that you have followed through Chapter 1, Creating Our First App with Ionic 2, to set up the environment and Ionic CLI. If you already had Ionic 1, it must be updated. For this, you can use the same command line as to install, which is as follows:

$ sudo npm install -g cordova ionic ios-sim

How to do it…

The following are the instructions:

  1. Create a new PagesAndTabs app using the tabs template and go into the PagesAndTabs folder to start Visual Studio Code, as shown:
    $ ionic start PagesAndTabs tabs --v2 
    $ cd PagesAndTabs
    $ code .
    
  2. The blank template only gives you a basic page. Open the Finder app in Mac or Windows Explorer in Windows to see the following folder structure:
    How to do it…

    Tip

    You will only modify what is inside the /src folder and not /www, as in Ionic 1. Everything in the /src folder will be built, and the /www folder will be created automatically. We will also reserve the folder names and filenames as much as possible, since the main goal here is to understand how the tab template works and the areas you can modify.

  3. Open and edit the /src/pages/tabs/tabs.html template file with the following code:
    <ion-tabs>
      <ion-tab [root]="tab1Root" tabTitle="One" tabIcon="water"></ion-tab>
      <ion-tab [root]="tab2Root" tabTitle="Two" tabIcon="leaf"></ion-tab>
      <ion-tab [root]="tab3Root" tabTitle="Three" tabIcon="flame"></ion-tab>
    </ion-tabs>

    Tip

    The new template only updates the title and icons. This is because this example wants to reserve the naming of tab root variables. You could add more tabs using <ion-tab>, as needed.

  4. To add a page, you need to ensure that tab1Root points to an existing folder and template. Since you will reuse the existing tab structure, you can just modify the /src/pages/home/home.html template, as shown, as this is your first page:
    <ion-header>
      <ion-navbar>
        <ion-title>One</ion-title>
      </ion-navbar>
    </ion-header>
    
    <ion-content padding>
      <h2>Welcome to Ionic 2 Tabs!</h2>
      <p>
        This starter project comes with simple tabs-based layout for apps
        that are going to primarily use a Tabbed UI.
      </p>
    </ion-content>
  5. Also, in the same /home, folder, edit home.ts that corresponds to the same template, and enter the code here:
    import { Component } from '@angular/core';
    
    import { NavController } from 'ionic-angular';
    
    @Component({
      selector: 'page-home',
      templateUrl: 'home.html'
    })
    export class HomePage {
    
      constructor(public navCtrl: NavController) {
    
      }
    
      ionViewWillEnter() {
        console.log('Enter Page 1');
      }
    
    }
  6. For the second page, tab2Root, you will follow a similar process by editing the /src/pages/about/about.html template, as shown:
    <ion-header>
      <ion-navbar>
        <ion-title>
          Two
        </ion-title>
      </ion-navbar>
    </ion-header>
    
    <ion-content>
      <ion-list>
        <ion-item>
          <ion-input type="text" placeholder="First Name"></ion-input>
        </ion-item>
    
        <ion-item>
          <ion-input type="text" placeholder="Last Name"></ion-input>
        </ion-item>
      </ion-list>
      <div padding>
        <button ion-button primary block>Create Account</button>
      </div>
    </ion-content>
  7. Edit about.ts, in the same folder from the preceding step:
    import { Component } from '@angular/core';
    import { NavController } from 'ionic-angular';
    
    @Component({
      selector: 'page-about',
      templateUrl: 'about.html'
    })
    export class AboutPage {
    
      constructor(public navCtrl: NavController) {
    
      }
    
      ionViewWillEnter() {
        console.log('Enter Page 2');
      }
    }
  8. Finally, for the tab3Root page, you can change the template so that it will show a slider in /src/pages/contact/contact.html, as follows:
    <ion-header>
      <ion-navbar>
        <ion-title>
          Three
        </ion-title>
      </ion-navbar>
    </ion-header>
    
    <ion-content>
      <ion-slides #mySlider index=0 (ionDidChange)="onSlideChanged($event)">
    
        <ion-slide style="background-color: green">
          <h2>Slide 1</h2>
        </ion-slide>
    
        <ion-slide style="background-color: blue">
          <h2>Slide 2</h2>
        </ion-slide>
    
        <ion-slide style="background-color: red">
          <h2>Slide 3</h2>
        </ion-slide>
    
      </ion-slides>
    </ion-content>
  9. In the /contact folder, you need to edit contact.ts with the following code:
    import { Component, ViewChild } from '@angular/core';
    import { Slides, NavController } from 'ionic-angular';
    
    @Component({
      selector: 'page-contact',
      templateUrl: 'contact.html'
    })
    export class ContactPage {
      @ViewChild('mySlider') slider: Slides;
    
      constructor(public navCtrl: NavController) {
    
      }
      
      ionViewWillEnter() {
        console.log('Enter Page 3');
      }
    
      onSlideChanged(e) {
        let currentIndex = this.slider.getActiveIndex();
        console.log("You are on Slide ", (currentIndex + 1));
      }
    
    }
  10. Go to your terminal and type the following command line to run the app:
    $ ionic serve
    

How it works…

There is actually a lot of new information and a lot of concepts in this simple app. At a higher level, this is how the app is structured:

  • When you run the app, Cordova loads the /www/index.html file first to open. All of your code and templates are combined into one file, /www/build/main.js.
  • The /app folder is where most of your logic belongs. It starts with app.component.ts as the Bootstrap file.
  • Each subfolder under the /pages folder will represent a page, which is a new concept in Ionic 2. A page consists of an HTML template, TypeScript code, and an .scss file to customize that specific template only.
  • The /theme folder will contain variables and customizations at the global level to override the default theme from Ionic 2.

Now, let's start with everything inside the /app folder.

The app.component.ts file only imports all the required pages and components to start the app. This example needs the following four imports by default:

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import { TabsPage } from '../pages/tabs/tabs';

You must always import Component, Platform, and StatusBar from Ionic, because that will give you the @Component decorator to Bootstrap your app. A decorator is placed in front of its class to provide metadata for the class. The following example tells that the MyApp class has the characteristics of a component with a template property:

@Component({
  template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
  rootPage = TabsPage;

  constructor(platform: Platform) {
    platform.ready().then(() => {
      StatusBar.styleDefault();
    });
  }
}

Since this is a simple example, you don't need to declare a lot except the template information. Similar to Ionic 1, you can use either template or templateUrl to point to a local file.

Class is another new concept in ES6. However, developers have been declaring class in various programming languages, such as Java and C#. In ES6, you can use class to be able to efficiently reuse code with better abstraction. A class could exist within that file context only. Consider the following example:

class Example {}

However, if you want to use that class somewhere else, you have to export:

export class Example {}

In a class, you can have the following:

Another nice thing about ES6 here is the arrow function, as shown:

platform.ready().then(() => {

});

The preceding is the same as:

platform.ready().then(function() {

});

An example (by passing a parameter) is as follows:

var a1 = a.map( s => s.length );

The same code can be rewritten as shown:

var a1 = a.map(function(s){ return s.length });

One important thing in app.component.ts is that you must declare a root page. You can see that from the template via [root]="rootPage",and then again in the constructor via this.rootPage = TabsPage. The square brackets, [], around root mean that it's a property of that DOM node. This is a new concept from Angular 2 as it's trying to get rid of using a DOM property, such as ngmodel (which tends to result in lower performance). The assignment here is to tell Ionic 2 that you will use TabsPage, which was imported earlier, and assign that as a root page. Then, the ion-nav directive will look at its own root property to start rendering the page. There seem to be a lot of abstractions and boilerplate compared to Ionic 1. However, this practice is recommended to ensure better separation and scaling.

Once you understand how app.component.ts works, it's easier to grasp the concepts from the other pages. Let's take a look at the /pages/tabs/tabs.ts file because that is where you define the TabsPage class. From this file, you need to import three other pages, which are the following:

import { Component } from '@angular/core';
import { HomePage } from '../home/home';
import { AboutPage } from '../about/about';
import { ContactPage } from '../contact/contact';

The template for this page is in tabs.html. However, you could also put the template in a string inside the .ts file, as follows:

@Component({
  template:
  ` <ion-tabs>
      <ion-tab [root]="tab1Root" tabTitle="One" tabIcon="water"></ion-tab>
      <ion-tab [root]="tab2Root" tabTitle="Two" tabIcon="leaf"></ion-tab>
      <ion-tab [root]="tab3Root" tabTitle="Three" tabIcon="flame"></ion-tab>
   </ion-tabs>`
})

ES6 also introduces a new feature, called a multiline template string. You probably realize that the preceding template string does not have any join() or string combine (+) operator. The reason is that you can use back-tick (` `) to allow a multiline template.

So, instead of doing this:

console.log("string text line 1
"+
"string text line 2");

You can now do this:

console.log(`string text line 1
string text line 2`);

Below the page decorator, you need to export TabsPage (so that you can use in app.component.ts) and tell the constructor to use tab1Root, tab2Root, and tab3Root as root, as shown, for other pages in tab navigation:

export class TabsPage {
  tab1Root: any = HomePage;
  tab2Root: any = AboutPage;
  tab3Root: any = ContactPage;
  
  constructor() {
  }
}

Ionic 2 tab declaration is very similar to Ionic 1, shown as follows:

<ion-tabs>
    <ion-tab><ion-tab>
</ion-tabs>

You just have to make sure that the root property is pointing to another page.

tab1Root is actually very simple to understand because it's a text page where you add your own content and design within the <ion-content> element, as shown:

<ion-content padding>
  <h2>Welcome to Ionic 2 Tabs!</h2>
  <p>
    This starter project comes with simple tabs-based layout for apps that are going to primarily use a Tabbed UI.
  </p>
</ion-content>

If you want to change the title, you can simply change the following line:

<ion-title>One</ion-title>

tab2Root and tab3Root are very similar in terms of how they are structured. Ionic 2 gives you the convenience of binding to an event right in the page class, as shown:

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

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

  constructor(public navCtrl: NavController) {

  }

  ionViewWillEnter() {
    console.log('Enter Page 2');
  }
}

In the preceding example from about.ts, if the user enters tab2Root, it will call the ionViewWillEnter () function automatically. This is a significant improvement because, in Ionic 1, you had to use $ionicView.enter on the $scope variable. Again, the concept of $scope no longer exists in Angular 2.

For a scalable app, it's better to separate templates into different files and avoid co-mingling templates inside the JavaScript code. The templateUrl must always point to the relative location of the .html file.

In ./src/pages/contact/contact.html, you can use slider box and bind to slide the change event, as shown:

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

<ion-content>
  <ion-slides #mySlider index=0 (ionDidChange)="onSlideChanged($event)">

    <ion-slide style="background-color: green">
      <h2>Slide 1</h2>
    </ion-slide>

    <ion-slide style="background-color: blue">
      <h2>Slide 2</h2>
    </ion-slide>

    <ion-slide style="background-color: red">
      <h2>Slide 3</h2>
    </ion-slide>

  </ion-slides>
</ion-content>

To get an event in Angular 2 (or Ionic 2), you have to use the parentheses, ( ), because the concept of ng-click or similar is no longer available. In this case, if the slide is changed based on ionDidChange, the ion-slides directive will trigger the onSlideChanged() function in the ContactPage class.

You cannot really run the TypeScript directly without having TypeScript to transpile the code into JavaScript. This process happens automatically behind the scenes when you run ionic serve. Also, when you change some code in the project, Ionic will detect the changes and rebuild the files before updating the browser. There is no need to hit the Refresh button every time.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.32.46