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:
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:
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
The following are the instructions:
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 .
Finder
app in Mac or Windows Explorer in Windows to see the following folder structure: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.
/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>
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>
/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'); } }
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>
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'); } }
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>
/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)); } }
$ ionic serve
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:
/www/index.html
file first to open. All of your code and templates are combined into one file, /www/build/main.js
./app
folder is where most of your logic belongs. It starts with app.component.ts
as the Bootstrap file./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./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:
this.a
or this.b
doSomething()
More information about classes can be found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes.
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 });
More information about arrow function can be found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions.
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.
3.142.212.196