By Danyal Zia | 2/13/2017 | General |Beginners

Ionic 2 -Building a Todo list application

Ionic 2 -Building a Todo list application

In my previous article, I made an introduction to Ionic 2 Integration with Firebase. We built an app that is connected with Firebase, but we used only the Real-time Database functionality of Firebase and the user authentication, meaning, we currently don’t have any protocol to restrict the users from accessing the “Show Data” page and we are not realizing the full potential of Firebase either.

Thankfully, Firebase not only supports the creation of users, but also their authorization with its built-in supported code and formats (i.e., email, Facebook, Twitter, Google, etc.), so most of the time we will be copying and pasting the code all over the place for user authentication, thanks to the great reusability Ionic 2 provides.

With the recent release of Firebase 3, many code examples found online have become obsolete, plus Ionic 2 uses TypeScript, so new versions often don’t support typings (for instance, the lack of AngularFire support). This results in extreme frustration for the beginners who just want a working piece of code from the internet to test the flavor of the library.

In this article, I am going to transform our previous application to a Todo list creation app and we will use user authentication to restrict the users from specific functionalities. Let’s get started!

User authentication and building a Todo list

Like I mentioned earlier, we didn’t implement the proper user authentication in our previous article, as we were simply checking if the user is signed-in or not but not utilizing the Auth service to restrict the users to access certain page/functionality.

You don’t need to create a new project, as we will be building on our previous project.

Let’s first install Firebase (specifically Firebase 3!), because we will be needing the modules. Previously we used the CDN (content delivery network) approach, meaning we called the external JavaScript Firebase library in our “index.html” file which simply exposes the “firebase” variable for usage in TypeScript. The problem with this approach is that we can’t use typings, so the code will look like the JavaScript code with no static typing support!

So… what does that mean? Well, we need to go with the NPM approach if we want our code to look as similar as possible. It basically means that we are going to install firebase as if it’s a typical Ionic/AngularJS module.

But before installing Firebase, you need to update your Ionic version, because the recent version has some requirements for allowing the installation of firebase, otherwise it will give you “firebase” namespace errors. You can visit the link (https://github.com/driftyco/ionic/blob/master/CHANGELOG.md#200-rc5-2017-01-11) and apply the configuration in your project.

Specifically, you need to change your “dependencies” and “devDependencies” arrays in “package.json” that mirror with the one provided in the link (apart from uninstalling and installing ionic of course!).

Make sure that “sw-toolbox” is included as that’s a recent inclusion that is necessary, otherwise Firebase will give errors. Once it is configured, add the firebase library as well in the “dependencies”. Here is my “package.json”:

package.json

 

{
 "name": "ionic-app-base",
 "author": "Ionic Framework",
 "homepage": "http://ionicframework.com/",
 "private": true,
 "scripts": {
   "clean": "ionic-app-scripts clean",
   "build": "ionic-app-scripts build",
   "ionic:build": "ionic-app-scripts build",
   "ionic:serve": "ionic-app-scripts serve"
 },
 "dependencies": {
   "@angular/common": "2.2.1",
   "@angular/compiler": "2.2.1",
   "@angular/compiler-cli": "2.2.1",
   "@angular/core": "2.2.1",
   "@angular/forms": "2.2.1",
   "@angular/http": "2.2.1",
   "@angular/platform-browser": "2.2.1",
   "@angular/platform-browser-dynamic": "2.2.1",
   "@angular/platform-server": "2.2.1",
   "@ionic/storage": "1.1.7",
   "angular2-datatable": "^0.5.2",
   "firebase": "^3.6.1",
   "ionic-angular": "2.0.0-rc.5",
   "ionic-native": "2.2.11",
   "ionicons": "3.0.0",
   "rxjs": "5.0.0-beta.12",
   "sw-toolbox": "3.4.0",
   "zone.js": "0.6.26"
 },
 "devDependencies": {
   "@ionic/app-scripts": "1.0.0",
   "typescript": "2.0.9"
 }
}

Once it’s configured, then do “npm install” to install the required modules. Btw, if you already have “node_modules/” in your root directory, then delete this folder first and do “npm install”, otherwise new updates/changes might conflict with the older ones.

Once it is installed, create two providers:

$ionic g provider data.service

$ionic g provider user.service

This will create two files in the “providers/” folder. Create two new folders with the same name as that of the files, and copy the files to their respective folders. This is done for the sake of naming convention, because our pages have their separate folders!

Providers are basically the services that perform some tasks for us in the background, like monitoring if the device is connected, doing asynchronous operations, etc. We can either inject the service in the root component (our app.component.ts I mean…) or individual components. Basically, anything that does some operation and is required by other components/pages several times, then we can make a component a provider and inject it whenever we need it.

You need to edit the content of the files. Following is the complete content of “data.service.ts”:

data.service.ts

 

import {Injectable} from '@angular/core';
import firebase from 'firebase';
import { Storage } from '@ionic/storage';
@Injectable()
export class DataService {
   public db: any;
   public staticData: any;
   constructor(public storage: Storage) {}
   init() {
const config = {
apiKey: "AIzaSyBcSXHF8LARZQJDoWSoLGuQO6DMAm6KDMo",
authDomain: "awesome-app-ionic.firebaseapp.com",
databaseURL: "https://awesome-app-ionic.firebaseio.com",
storageBucket: "awesome-app-ionic.appspot.com",
messagingSenderId: "931508989005"
};

firebase.initializeApp(config);
this.db = firebase.database().ref('/');
this.staticData = firebase.database().ref('/static');
   }
getData() {
return this.storage.get('todos');  
 }

 save(data){
   let newData = JSON.stringify(data);
   this.storage.set('todos', newData);
 }
}

Here, I have added the Firebase config. You need to edit it and add the config of your Firebase project. This service is calling/using some todo code which I will explain later. “Storage” service provides an easy way to store the key/value pairs of the data, so for instance, if your application is running on a particular platform, then it will use the storage engine optimized for the platform.

Now open the “user.service.ts” and copy the following content:

user.service.ts

 

import {Injectable} from '@angular/core';

import firebase from 'firebase';

@Injectable()
export class UserService {
   public auth: any;
   constructor() {
       this.auth = firebase.auth();
   }

   public login(userEmail: string, userPassword: string) {
       return new Promise((resolve, reject) => {
           this.auth.signInWithEmailAndPassword(userEmail, userPassword)
               .then(userData => resolve(userData),
                   err => reject(err));
       });
   }

   public logout() {
       return this.auth.signOut();
   }
}

This should be self-explanatory.

Now, you need to create the pages for the todo list.

 

$ionic g page todo

$ionic g page todo-add-item

$ionic g page todo-item-info

We are not just creating a todo page, but also two pages for holding adding functionality and info functionality.

Open the “todo.ts” and copy the following content:

todo.ts

 

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

import { ModalController } from 'ionic-angular';

import { DataService } from '../../providers/data/data.service';

import { TodoAddItem } from '../todo-add-item/todo-add-item'
import { TodoItemInfo } from '../todo-item-info/todo-item-info';

import { ChangeDetectorRef } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';

import { UserService } from '../../providers/user/user.service';

@Component({
 selector: 'page-todo',
 templateUrl: 'todo.html'
})
export class TodoPage {
// For Login
public userEmail: string;
public userPassword: string;

public authStatus: boolean;
public message: string;

private isAuth: BehaviorSubject<boolean>;

ionViewDidLoad() {
console.log('ionViewDidLoad TodoPage');
this._user.auth.onAuthStateChanged(user => {
this.isAuth.next(!!user);
this._cd.detectChanges();
});
}

public items = [];
constructor(public navCtrl: NavController, private _data: DataService, public modalCtrl: ModalController, private _user:UserService, private _cd:ChangeDetectorRef){
 
this.isAuth = new BehaviorSubject(false);

this.isAuth.subscribe(val => this.authStatus = val);
this._data.getData().then((todos) => {

if(todos){
this.items = JSON.parse(todos);
}

});
}

addItem(){

let addModal = this.modalCtrl.create(TodoAddItem);

addModal.onDidDismiss((item) => {
if(item){
this.storeItem(item);
}
});

addModal.present();
}

storeItem(item){
this.items.push(item);
}

showItem(item){
// Let's pass the item param
this.navCtrl.push(TodoItemInfo, {
 item: item
});
}

public logout() {
this._user.logout()
}

public login() {
this._user.login(this.userEmail, this.userPassword)
}
}

Here, we are using the “BehaviorSubject” which is the kind of observable with some changes, for example, it needs an initial value, meaning it always returns a value on subscription even when it isn’t receiving the next value! Basically, we are doing the Auth operation and checking whether the change happened or not.

We are also using DataService to pass the todo values back and forth.

Now, open the “todo.html” and copy the following content:

todo.html

 

<ion-header>
 <ion-navbar>
   <button ion-button menuToggle>
     <ion-icon name="menu"></ion-icon>
   </button>
   <ion-title>Todo</ion-title>
 </ion-navbar>
</ion-header>

<ion-content padding>
<div *ngIf='!authStatus'>
<h3>You need to login to see the Todo list</h3>
   <form (ngSubmit)="login()">
       <ion-list>
           <ion-item>
               <ion-label stacked>Email</ion-label>
               <ion-input [(ngModel)]="userEmail"
                          type="email" name="userEmail"></ion-input>
           </ion-item>

           <ion-item>
               <ion-label stacked>Password</ion-label>
               <ion-input [(ngModel)]="userPassword"
                          type="password" name="userPassword"></ion-input>
           </ion-item>

           <hr/>
           <button type="submit" ion-button>Login!</button>
       </ion-list>
   </form>
</div>
<div *ngIf='authStatus'>
<button ion-button (click)="addItem()">Add Item</button>
<ion-list>
<ion-item *ngFor="let item of items" (click)="showItem(item)">{{item.title}}</ion-item>
</ion-list>
<button (click)='logout()' ion-button>Logout</button>
</div>
</ion-content>

This shouldn’t be difficult to understand. Basically, we are using the *ngIf directive to render the content in specific cases.

Now, open the “todo-add-item.ts” and copy the following content:

todo-add-item.ts

 

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

@Component({
 selector: 'todo-add-item',
 templateUrl: 'todo-add-item.html'
})
export class TodoAddItem {

title;
description;

constructor(public nav: NavController, public view: ViewController) {

}

ionViewDidLoad() {
console.log('ionViewDidLoad TodoAddItem');
}
 
storeItem(){

let newItem = {
 title: this.title,
 description: this.description
};

this.view.dismiss(newItem);

}

close(){
this.view.dismiss();
}
}

Now we need to update its corresponding HTML as well. Copy the following content to “todo-add-item.html”:

todo-add-item.html

 

<ion-header>
 <ion-toolbar color="secondary">
  <ion-title>
  Add Item
  </ion-title>
    <ion-buttons end>
    <button ion-button icon-only (click)="close()"><ion-icon name="close"></ion-icon></button>
    </ion-buttons>
   </ion-toolbar>
</ion-header>

<ion-content>
<ion-list>

 <ion-item>
   <ion-label floating>Title</ion-label>
   <ion-input type="text" [(ngModel)]="title"></ion-input>
 </ion-item>

 <ion-item>
   <ion-label floating>Description</ion-label>
   <ion-input type="text" [(ngModel)]="description"></ion-input>
 </ion-item>

</ion-list>

<button full ion-button color="secondary" (click)="storeItem()">Save</button>

</ion-content>

This code should be self-explanatory.

Now, open the “todo-item-info.ts” and copy the following content:

todo-item.info.ts

 

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

@Component({
 selector: 'page-todo-item-info',
 templateUrl: 'todo-item-info.html'
})
export class TodoItemInfo {

 title;
 description;

 constructor(public navParams: NavParams) {

 }

 ionViewDidLoad() {
console.log('ionViewDidLoad TodoItemInfo');
   this.title = this.navParams.get('item').title;
   this.description = this.navParams.get('item').description;
 }

}

Now copy the following content to “todo-item-info.html”:

todo-item-info.html

<ion-header>
 <ion-navbar color="secondary">
   <ion-title>
     {{title}}
   </ion-title>
 </ion-navbar>
</ion-header>

<ion-content>
 <ion-card>
   <ion-card-content>
     {{description}}
   </ion-card-content>
 </ion-card>
</ion-content>

This code should be self-explanatory, so let’s skip the explanation.

Now, create a new page “auth”:

$ionic g page auth

This page will contain the code for the sample authentication. Basically, it’s a test where we would be reading some static data from our JSON database on Firebase. The data will only be shown if the users are logged-in. What do I mean by static data? Basically an isolated key/value addition in the JSON file that doesn’t have any class.

The same auth service is being used by every page that requires the login, so if you have logged-in once, then you don’t need to login again.

Copy the following content to “auth.ts”:

auth.ts

 

import { Component, ChangeDetectorRef } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';

import { DataService } from '../../providers/data/data.service';
import { UserService } from '../../providers/user/user.service';

@Component({
   templateUrl: './auth.html',
})
export class AuthPage {
public userEmail: string;
public userPassword: string;

public authStatus: boolean;
public message: string;

private isAuth: BehaviorSubject<boolean>;

constructor(private _data:DataService, private _user:UserService, private _cd:ChangeDetectorRef) {
this.isAuth = new BehaviorSubject(false);

this.isAuth.subscribe(val => this.authStatus = val);
}

ionViewDidLoad() {
Promise.all([this.fetchMessage()]);

this._user.auth.onAuthStateChanged(user => {
this.isAuth.next(!!user);
this._cd.detectChanges();
});
}

private fetchMessage() {
return new Promise(res => {
 this._data.db.child('static').on('value', data => {
this.message = data.val();
res();
 });
});
}

public logout() {
this._user.logout()
}

public login() {
this._user.login(this.userEmail, this.userPassword)
}
}

Now you need to edit the HTML as well. Copy the following content to “auth.html”:

auth.html

 

<ion-header>
   <ion-navbar>
<button ion-button menuToggle>
     <ion-icon name="menu"></ion-icon>
   </button>
       <ion-title>
           Authentication Test
       </ion-title>
   </ion-navbar>
</ion-header>

<ion-content padding>
<div *ngIf='!authStatus'>
<h3>You need to login to see the data</h3>
   <form (ngSubmit)="login()">
       <ion-list>
           <ion-item>
               <ion-label stacked>Email</ion-label>
               <ion-input [(ngModel)]="userEmail"
                          type="email" name="userEmail"></ion-input>
           </ion-item>
           <ion-item>
               <ion-label stacked>Password</ion-label>
               <ion-input [(ngModel)]="userPassword"
                          type="password" name="userPassword"></ion-input>
           </ion-item>

           <hr/>
           <button type="submit" ion-button>Login!</button>
       </ion-list>
   </form>
</div>
<div *ngIf='authStatus'>
<p><strong>Some Data</strong> {{message}}</p>
<button (click)='logout()' ion-button>Logout</button>
</div>
</ion-content>

First we are using the similar Auth mechanism that we used earlier. Second we are calling a database reference on “static” child, which gives us the value of “static” in our JSON file. We will add the JSON file later.

Now, time to modify our previous pages. Let’s first sort out the sign-in/sign-up page!

Open the “signin.ts” and copy the following content:

signin.ts

 

import { Component, ChangeDetectorRef } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';

import { DataService } from '../../providers/data/data.service';
import { UserService } from '../../providers/user/user.service';

import { ShowdataPage } from '../showdata/showdata';

import { NavController } from 'ionic-angular';

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

public userEmail: string;
public userPassword: string;

public authStatus: boolean;
public message: string;

private isAuth: BehaviorSubject<boolean>;

   constructor(public nav: NavController, private _data:DataService, private _user:UserService, private _cd:ChangeDetectorRef) {
this.nav = nav;
this.isAuth = new BehaviorSubject(false);

this.isAuth.subscribe(val => this.authStatus = val);
}

ionViewDidLoad() {
console.log('ionViewDidLoad SigninPage');
this._user.auth.onAuthStateChanged(user => {
this.isAuth.next(!!user);
this._cd.detectChanges();
});
}

public logout() {
this._user.logout()
}

public login() {
this._user.login(this.userEmail, this.userPassword)
}

   ngOnInit():any {

   }
}

Now copy the following content to “signin.html”:

signin.html

 

<ion-header>

   <ion-navbar>
   <button ion-button menuToggle>
     <ion-icon name="menu"></ion-icon>
   </button>
   <ion-title>Sign-in</ion-title>
 </ion-navbar>

</ion-header>

<ion-content padding>

<div *ngIf='!authStatus'>
<h3>You need to login to see the data</h3>
   <form (ngSubmit)="login()">
       <ion-list>
           <ion-item>
               <ion-label stacked>Email</ion-label>
               <ion-input [(ngModel)]="userEmail"
                          type="email" name="userEmail"></ion-input>
           </ion-item>

           <ion-item>
               <ion-label stacked>Password</ion-label>
               <ion-input [(ngModel)]="userPassword"
                          type="password" name="userPassword"></ion-input>
           </ion-item>

           <hr/>
           <button type="submit" ion-button>Login!</button>
       </ion-list>
   </form>
</div>
<div *ngIf='authStatus'>
<button (click)='logout()' ion-button>Logout</button>
</div>
</ion-content>

Basically, the modification here is that we are using the new login code along with the Auth mechanism.

Now open the “signup.ts” and copy the following content:

signup.ts

 

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

import { FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms";

import { AuthService } from "../../app/auth.service";

@Component({
 selector: 'page-signup',
 templateUrl: 'signup.html'
})
export class SignupPage implements OnInit {

 constructor(public navCtrl: NavController, public navParams: NavParams, private fb: FormBuilder, private authService: AuthService) {}

 ionViewDidLoad() {
   console.log('ionViewDidLoad SignupPage');
 }

 myForm: FormGroup;
   error = false;
   errorMessage = '';

   onSignup() {
     this.authService.signupUser(this.myForm.value);
   }

   ngOnInit(): any {
       this.myForm = this.fb.group({
           email: ['', Validators.compose([
               Validators.required,
               this.isEmail
           ])],
           password: ['', Validators.required],
           confirmPassword: ['', Validators.compose([
               Validators.required,
               this.isEqualPassword.bind(this)
           ])],
       });
   }

   isEmail(control: FormControl): {[s: string]: boolean} {
       if (!control.value.match(/^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/)) {
           return {noEmail: true};
       }
   }

   isEqualPassword(control: FormControl): {[s: string]: boolean} {
       if (!this.myForm) {
           return {passwordsNotMatch: true};

       }
       if (control.value !== this.myForm.controls['password'].value) {
           return {passwordsNotMatch: true};
       }
   }
}

Now copy the following content to “signup.html”:

signup.html

 

<ion-header>
 <ion-navbar>
   <button ion-button menuToggle>
     <ion-icon name="menu"></ion-icon>
   </button>
   <ion-title>Sign-up</ion-title>
 </ion-navbar>
</ion-header>

<ion-content padding>

<h3>Sign-up to see the Employee page</h3>
<form [formGroup]="myForm" (ngSubmit)="onSignup()">
     <ion-item>
       <ion-label>E-Mail</ion-label>
       <ion-input formControlName="email" type="email" id="email" #email class="form-control"></ion-input>
<span *ngIf="!email.pristine && email.errors != null && email.errors['noEmail']">Invalid mail address</span>
     </ion-item>
     <ion-item>
       <ion-label>Password</ion-label>
       <ion-input formControlName="password" type="password" id="password" class="form-control"></ion-input>
     </ion-item>
 <ion-item>
       <ion-label for="confirm-password">Confirm Password</ion-label>
       <ion-input formControlName="confirmPassword" type="password" id="confirm-password" #confirmPassword class="form-control"></ion-input>
<span *ngIf="!confirmPassword.pristine && confirmPassword.errors != null && confirmPassword.errors['passwordsNotMatch']">Passwords do not match</span>
     </ion-item>
     <button ion-button type="submit" [disabled]="!myForm.valid">Sign up</button>
   </form>
</ion-content>

This is pretty self-explanatory.

To use table, or not?

Now the time has come to change our showdata page. The angular2-datatable that we were using earlier was not rendering properly on the screen, because it uses Bootstrap themes, and adding Bootstrap to Ionic 2 can  really mess things up (not quite everything, but some component stuff). So I decided to use the simple <ion-list> instead, because the information we are rendering is not complicated enough to require a table.

Open the “showdata.ts” and copy the following content:

showdata.ts

 

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

import { ChangeDetectorRef } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';

import { UserService } from '../../providers/user/user.service';

import firebase from 'firebase';

@Component({
 selector: 'page-showdata',
 templateUrl: 'showdata.html'
})
export class ShowdataPage implements OnInit {

public usersArray: any;

public authStatus: boolean;

private isAuth: BehaviorSubject<boolean>;
ionViewDidLoad() {
console.log('ionViewDidLoad ShowdataPage');
this._user.auth.onAuthStateChanged(user => {
this.isAuth.next(!!user);
this._cd.detectChanges();
});
}
constructor(public navCtrl: NavController, public navParams: NavParams, private _user:UserService, private _cd:ChangeDetectorRef) {
this.navCtrl = navCtrl;
this.isAuth = new BehaviorSubject(false);

this.isAuth.subscribe(val => this.authStatus = val);
// Let's set the data from the code!
firebase.database().ref('users/' + "uid1").set({
employeeName: "Peter",
daysWork: "12 Days",
hourlyRate : "$76.11"
});

var self = this;

var ref = firebase.database().ref('/users/');
ref.once('value').then(function(snapshot) {
// We need to create this array first to store our local data
let rawList = [];
snapshot.forEach( snap => {
rawList.push({
 id: snap.key,
 employeeName: snap.val().employeeName,
 daysWork: snap.val().daysWork,
 hourlyRate: snap.val().hourlyRate,
});
 });
self.usersArray = rawList;
});
}

ngOnInit() {
}
}

Here, you can see that I am modifying the first user with the hardcoded values. You can change it to whatever you want.

Again, we need to edit the HTML. Copy the following content to “showdata.html”:

showdata.html

 

<ion-header>

   <ion-navbar>
   <button ion-button menuToggle>
     <ion-icon name="menu"></ion-icon>
   </button>
   <ion-title>Show Data</ion-title>
 </ion-navbar>

</ion-header>

<ion-content padding>
 
<div *ngIf='!authStatus'>
<h3>You need to sign-in (from Sign-in page) to see the data</h3>
</div>
<div *ngIf='authStatus'>
<ion-list>
   <ion-item *ngFor="let user of usersArray">
 <p>Id: <strong>{{user?.id}}</strong></p>
 <p>Employee Name: <strong>{{user?.employeeName}}</strong></p>
     <p>Days Work: <strong>{{user?.daysWork}}</strong></p>
     <p>Hourly Rate: <strong>{{user?.hourlyRate}}</strong></p>
   </ion-item>
</ion-list>
</div>
</ion-content>

Now you need to import the JSON file to your Firebase console. Just go to the “Database” section and click on “Import JSON” to import the file. Here is my JSON file:

data.json

{
"static": "Static Message",

"users": {
"uid1": {
"employeeName": "Richard",
"daysWork": "15 Days",
"hourlyRate": "$11.11"
},
"uid2": {
"employeeName": "John",
"daysWork": "30 Days",
"hourlyRate": "$20.88"
},
"uid3": {
"employeeName": "Ali",
"daysWork": "22 Days",
"hourlyRate": "$15.67"
},
"uid4": {
"employeeName": "Raza",
"daysWork": "22 Days",
"hourlyRate": "$34.28"
}
}
}

You can add your own data, just make sure it is in valid JSON format. You can validate your JSON from here (http://jsonlint.com/).

Make sure your “Rules” are set like the following:

 

{
 "rules": {
   ".read": "true",
   ".write": "auth != null",
 }
}

Our homepage is pretty much untouched, just make sure that it is plain and doesn’t contain any additional code.

Now we need to add everything in our Main app component and module. Open the “app.component.ts” and copy the following content:

app.component.ts

 

import { Component, ViewChild } from '@angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';

import { HomePage } from '../pages/home/home';
import { SigninPage } from '../pages/signin/signin';
import { SignupPage } from '../pages/signup/signup';
import { ShowdataPage } from '../pages/showdata/showdata';
import { AuthPage } from '../pages/auth/auth';
import { TodoPage } from '../pages/todo/todo';

import { AuthService } from "./auth.service";
import { DataService } from '../providers/data/data.service';

@Component({
 templateUrl: 'app.html'
})
export class MyApp {
 @ViewChild(Nav) nav: Nav;

 rootPage: any = HomePage;
 
 pages: Array<{title: string, component: any}>;

 constructor(public platform: Platform, private authService: AuthService, data: DataService) {
   this.initializeApp();
data.init();
   // used for an example of ngFor and navigation
   this.pages = [
     { title: 'Home', component: HomePage },
 { title: 'Sign-in', component: SigninPage },
 { title: 'Sign-up', component: SignupPage },
 { title: 'Show Data', component: ShowdataPage },
 { title: 'Auth Page', component: AuthPage },
 { title: 'Todo Page', component: TodoPage }
   ];
 }

 initializeApp() {
   this.platform.ready().then(() => {
     // Okay, so the platform is ready and our plugins are available.
     // Here you can do any higher level native things that you might need.
     StatusBar.styleDefault();
     Splashscreen.hide();
   });
 }

 openPage(page) {
   // Reset the content nav to have just this page
   // we wouldn't want the back button to show in this scenario
   this.nav.setRoot(page.component);
 }
 
 isAuth() {
   return this.authService.isAuthenticated();
 }

 onLogout() {
   this.authService.logout();
 }
}

Now open the “app.module.ts” and copy the following content:

app.module.ts

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { SigninPage } from '../pages/signin/signin';
import { SignupPage } from '../pages/signup/signup';
import { ShowdataPage } from '../pages/showdata/showdata';

import { AuthService } from "./auth.service";

import {DataTableModule} from "angular2-datatable";

import {
 ReactiveFormsModule
} from '@angular/forms';

import { AuthGuard } from "./auth.guard";

import { AuthPage } from '../pages/auth/auth';
import { TodoAddItem } from '../pages/todo-add-item/todo-add-item';
import { TodoItemInfo } from '../pages/todo-item-info/todo-item-info';
import { TodoPage } from '../pages/todo/todo';

import { DataService } from '../providers/data/data.service';
import { UserService } from '../providers/user/user.service';
import { Storage } from '@ionic/storage';

@NgModule({
 declarations: [
   MyApp,
   HomePage,
SigninPage,
SignupPage,
ShowdataPage,
AuthPage,
TodoAddItem,
   TodoItemInfo,
TodoPage
 ],
 imports: [
   IonicModule.forRoot(MyApp, {
tabsPlacement: 'bottom',
 platforms: {
android: {
 tabsPlacement: 'top'
},
ios: {
 tabsPlacement: 'top'
},
windows:
{
 tabsPlacement: 'top'
}
 }
}),
DataTableModule,
ReactiveFormsModule
 ],
 bootstrap: [IonicApp],
 entryComponents: [
   MyApp,
   HomePage,
SigninPage,
SignupPage,
ShowdataPage,
   AuthPage,
TodoAddItem,
   TodoItemInfo,
TodoPage
 ],
 providers: [Storage, DataService, UserService, AuthService, AuthGuard, {provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

You can see that I have added “Storage”, “DataService” and other providers in “providers” array.

This is what my “pages” directory looks like:

This is my Ionic version (when running the “ionic info”):

Ionic Framework Version: 2.0.0-rc.5

Ionic CLI Version: 2.2.1

Ionic App Lib Version: 2.2.0

Ionic App Scripts Version: 1.0.0

ios-deploy version: Not installed

ios-sim version: Not installed

OS: Windows 8.1

Node Version: v6.5.0

Xcode version: Not installed

If you do “ionic serve” now, then you can see the cool application.

If you click on “Show Data”, you will see that the values of first user have been changed.

That’s it for now! You can see that I have not currently implemented the “Storage” functionality plus the todo lists are not being created uniquely for every user. I think however the article and the application has become very long, so it will have to wait till the next article.

Conclusion

So this is how you can create user authentication in your application along with a Todo list in Ionic 2. The power of component-based programming in Ionic 2 makes it easy (well, not that easy actually) to develop a complex application from scratch within a few days as the reusability of the code has enhanced dramatically.

If you have any question or the code doesn’t compile or there’s anything you’d like to ask, just tell me in the comment section below. Till next time!

By Danyal Zia | 2/13/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now