Build Ionic 3, Angular 5 and Firebase Simple Chat App

by Didin J. on Jan 20, 2018 Build Ionic 3, Angular 5 and Firebase Simple Chat App

Step by step tutorial of how to build Ionic, Angular 5, Cordova and Firebase Simple Chat App

Comprehensive step by step tutorial of how to build Ionic, Angular 5, Cordova and Firebase simple chat app. The scenario for this app is filled Nickname then save to Firebase Database, choose chat rooms from ROOM list, inside chat room type and read chat messages. This time we will use Firebase module directly instead of using AngularFire.

Jumps to the steps:

The following tools, framework, and modules are required for this tutorial:

  1. Ionic 3
  2. Node.js
  3. Angular 5
  4. Firebase NPM Module
  5. Firebase/Google Account
  6. Terminal or Node.js Command Line
  7. IDE or Text Editor

Before moving to the steps, make sure you have installed the latest Node.js and Ionic 3. To check it, type this command in the terminal or Node.js command line.

node -v
v8.9.3
npm -v
5.5.1
ionic -v
3.19.0
cordova -v
7.1.0

That's the last version when this tutorial was written. For update Node.js and it's `npm` download from Node.js https://nodejs.org and choose the recommended version. For Ionic 3, type this command.

sudo npm i -D -E ionic@latest
sudo npm i -g cordova


Setup Google Firebase

Go to https://console.firebase.google.com and log in using your Google account to enter your Firebase dashboard.

Build Ionic 3, Angular 5 and Firebase Simple Chat App - Firebase Console

Click CREATE NEW PROJECT button, name it as you like (ours: GeoTracker) and choose your country. Finally, click CREATE PROJECT button.

Build Ionic 3, Angular 5 and Firebase Simple Chat App - Firebase Project Overview

Go to Develop menu then choose Database and click Get Started button. Click the RULES tab then edit to make your database writable and readable for everyone then click `PUBLISH` button.

Build Ionic 3, Angular 5 and Firebase Simple Chat App - Firebase Database Settings


Create a New Ionic 3, Angular 5 and Cordova App

To create a new Ionic 3, Angular 5 and Cordova app, type this command.

ionic start ionic-firebase-chat blank

You will see this output, then type `Y` for including Cordova to the app creation.

✔ Creating directory ./ionic-firebase-chat - done!
✔ Downloading and extracting blank starter - done!

? Would you like to integrate your new app with Cordova to target native iOS and Android? (y/N)

Just wait for a few minutes because it will also install NPM modules. Next, go to the newly created app folder.

cd ./ionic-firebase-chat

For sanitizing, run the app on the browser for the first time to make sure everything working properly.

ionic serve -l

And you will see this landing page of Ionic 3 and Angular 5 app.

Build Ionic 3, Angular 5 and Firebase Simple Chat App - Ionic 3 Blank


Install and Configure the Firebase Module

Firebase library ship with NPM module. For that, type this command to install the module.``

npm install --save [email protected]

Why are we using Firebase module version 4.8.0? because it's working version right now. It seems a lot of trouble when using the version larger than 4.8.0. So be careful choosing Firebase module version, otherwise, you like to experiment with the all-new version by your self. Next, register the Firebase module in the Ionic 3 Angular 5 app by open and edit this file `src/app.component.ts` then add this import of Firebase.

import * as firebase from ‘firebase’;

Declare a constant variable for holds Firebase setting (apiKey, authDomain, databaseURL, projectId, storageBucket) before `@Component`.

const config = {
  apiKey: 'YOUR_APIKEY',
  authDomain: 'YOUR_AUTH_DOMAIN',
  databaseURL: 'YOUR_DATABASE_URL',
  projectId: 'YOUR_PROJECT_ID',
  storageBucket: 'YOUR_STORAGE_BUCKET',
};

Add this line inside the constructor for running the Firebase configuration.

constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
  platform.ready().then(() => {
    // Okay, so the platform is ready and our plugins are available.
    // Here you can do any higher level native things you might need.
    statusBar.styleDefault();
    splashScreen.hide();
  });
  firebase.initializeApp(config);
}

Now, Firebase database is ready to populate.


Create Sign-in or Enter Nickname Page

To add a new page for sign in or enter a nickname, run this command.

ionic g page Signin

That command will create a new page bundle contains HTML, TS and SCSS files. Next, open and edit `src/pages/signin/signin.ts` then add this import of RoomPage.

import { RoomPage } from  '../room/room';

That import declares `RoomPage` that will add later. Now, add this variable before the constructor for hold sign-in data.

data = { nickname:"" };

Create this function for Sign In or Enter the Room using a specific nickname.

enterNickname() {
  this.navCtrl.setRoot(RoomPage, {
    nickname: this.data.nickname
  });
}

Open and edit `src/pages/signin/signin.html` then replace all tags with this login form.

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

<ion-content padding>
  <form (ngSubmit)="enterNickname()">
    <ion-list>
      <ion-item>
        <ion-label floating>Enter your Nickname</ion-label>
        <ion-input type="text" [(ngModel)]="data.nickname" name="nickname" required=""></ion-input>
      </ion-item>
      <ion-item>
        <button ion-button full round color="secondary" type="submit">Enter</button>
      </ion-item>
    </ion-list>
  </form>
</ion-content>


Create Room List and Add-Room Page

To add a new page for Room list and `add-room`, type this command.

ionic g page Room
ionic g page AddRoom

Open and edit `src/pages/room/room.ts` then replace all imports with this Component, IonicPage, NavController, NavParams, AddRoomPage, HomePage, and Firebase.

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { AddRoomPage } from '../add-room/add-room';
import { HomePage } from '../home/home';
import * as firebase from 'Firebase';

Declare variables before the constructor for hold room list and referencing Firebase database.

rooms = [];
ref = firebase.database().ref('chatrooms/');

Add this Firebase function to listening to any value changes from Firebase Database.

constructor(public navCtrl: NavController, public navParams: NavParams) {
  this.ref.on('value', resp => {
    this.rooms = [];
    this.rooms = snapshotToArray(resp);
  });
}

Add this constant function below the Class block for converting Firebase response to an array.

export const snapshotToArray = snapshot => {
    let returnArr = [];

    snapshot.forEach(childSnapshot => {
        let item = childSnapshot.val();
        item.key = childSnapshot.key;
        returnArr.push(item);
    });

    return returnArr;
};

Add this function under the constructor for navigating to `add-room` page.

addRoom() {
  this.navCtrl.push(AddRoomPage);
}

Add this function for join or navigating to Home Page of selected Room.

joinRoom(key) {
  this.navCtrl.setRoot(HomePage, {
    key:key,
    nickname:this.navParams.get("nickname")
  });
}

Now, open and edit `src/pages/room/room.html` then replace all tags with this.

<ion-header>
  <ion-navbar>
    <ion-title>Room</ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="addRoom()">
        <ion-icon name="add-circle"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
    <ion-item *ngFor="let room of rooms">
      {{room.roomname}}
      <ion-icon name="chatboxes" item-end (click)="joinRoom(room.key)"></ion-icon>
    </ion-item>
  </ion-list>
</ion-content>

Next, open and edit `src/pages/add-room/add-room.ts` then replace all imports with this.

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import * as firebase from 'Firebase';

Declare these variables before the constructor for hold data object and Firebase database reference.

data = { roomname:'' };
ref = firebase.database().ref('chatrooms/');

Add this function to the constructor for saving a new Room data to Firebase Database.

addRoom() {
  let newData = this.ref.push();
  newData.set({
    roomname:this.data.roomname
  });
  this.navCtrl.pop();
}

Now, open and edit `src/pages/add-room/add-room.html` then replace all tags with this.

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


<ion-content padding>
  <form (ngSubmit)="addRoom()">
    <ion-list>
      <ion-item>
        <ion-label floating>Enter Room Name</ion-label>
        <ion-input type="text" [(ngModel)]="data.roomname" name="roomname" required=""></ion-input>
      </ion-item>
      <ion-item>
        <button ion-button full round color="secondary" type="submit">Add</button>
      </ion-item>
    </ion-list>
  </form>
</ion-content>


Modify Home Page as Chat Page

Finally, we just need to modify the existing Home Page for Chat page. Open and edit `src/pages/home/home.ts` then replace all imports with this.

import { Component, ViewChild } from '@angular/core';
import { NavController, NavParams, Content } from 'ionic-angular';
import { RoomPage } from '../room/room';
import * as firebase from 'Firebase';

Declare content module on the first line of the Class block.

@ViewChild(Content) content: Content;

Following by adding these variables for the hold data object, chats array, room key, nickname and status for sign out.

data = { type:'', nickname:'', message:'' };
chats = [];
roomkey:string;
nickname:string;
offStatus:boolean = false;

Add this lines inside the constructor body.

constructor(public navCtrl: NavController, public navParams: NavParams) {
  this.roomkey = this.navParams.get("key") as string;
  this.nickname = this.navParams.get("nickname") as string;
  this.data.type = 'message';
  this.data.nickname = this.nickname;

  let joinData = firebase.database().ref('chatrooms/'+this.roomkey+'/chats').push();
  joinData.set({
    type:'join',
    user:this.nickname,
    message:this.nickname+' has joined this room.',
    sendDate:Date()
  });
  this.data.message = '';

  firebase.database().ref('chatrooms/'+this.roomkey+'/chats').on('value', resp => {
    this.chats = [];
    this.chats = snapshotToArray(resp);
    setTimeout(() => {
      if(this.offStatus === false) {
        this.content.scrollToBottom(300);
      }
    }, 1000);
  });
}

Create a function for sending a message that actually saves message data to Firebase database as room child.

sendMessage() {
  let newData = firebase.database().ref('chatrooms/'+this.roomkey+'/chats').push();
  newData.set({
    type:this.data.type,
    user:this.data.nickname,
    message:this.data.message,
    sendDate:Date()
  });
  this.data.message = '';
}

Create a function for exit or sign out from the current chat room. This also sends the message for exit status to Firebase database.

exitChat() {
  let exitData = firebase.database().ref('chatrooms/'+this.roomkey+'/chats').push();
  exitData.set({
    type:'exit',
    user:this.nickname,
    message:this.nickname+' has exited this room.',
    sendDate:Date()
  });

  this.offStatus = true;

  this.navCtrl.setRoot(RoomPage, {
    nickname:this.nickname
  });
}

Next, add this constant function after the Class body for converting Firebase response to an array.

export const snapshotToArray = snapshot => {
    let returnArr = [];

    snapshot.forEach(childSnapshot => {
        let item = childSnapshot.val();
        item.key = childSnapshot.key;
        returnArr.push(item);
    });

    return returnArr;
};

Now, open and edit `src/pages/home/home.html` then replace all tags with this.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Firebase Chat
    </ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="exitChat()">
        <ion-icon name="exit"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item *ngFor="let chat of chats" no-lines>
      <div class="chat-status" text-center *ngIf="chat.type==='join'||chat.type==='exit';else message">
        <span class="chat-date">{{chat.sendDate | date:'short'}}</span>
        <span class="chat-content-center">{{chat.message}}</span>
      </div>
      <ng-template #message>
        <div class="chat-message" text-right *ngIf="chat.user === nickname">
          <div class="right-bubble">
            <span class="msg-name">Me</span>
            <span class="msg-date">{{chat.sendDate | date:'short'}}</span>
            <p text-wrap>{{chat.message}}</p>
          </div>
        </div>
        <div class="chat-message" text-left *ngIf="chat.user !== nickname">
          <div class="left-bubble">
            <span class="msg-name">{{chat.user}}</span>
            <span class="msg-date">{{chat.sendDate | date:'short'}}</span>
            <p text-wrap>{{chat.message}}</p>
          </div>
        </div>
      </ng-template>
    </ion-item>
  </ion-list>
</ion-content>

<ion-footer>
  <ion-grid>
    <ion-row>
      <ion-col col-10>
        <ion-input type="text" placeholder="Type a message" [(ngModel)]="data.message" name="message"></ion-input>
      </ion-col>
      <ion-col col-2 (click)="sendMessage()">
        <ion-icon name="paper-plane"></ion-icon>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-footer>

To make your chat page more stylish, open and edit `src/pages/home/home.scss` then add this SCSS codes.

page-home {
  ion-content {
    background: url(../assets/imgs/chat-back.png) no-repeat center center fixed;
    background-size: cover;
    height: 100%;
    overflow: hidden;
    .item-md, .item-ios {
      background: none;
    }
  }
  ion-footer {
    background: white;
    ion-icon {
      padding: 10px;
      font-size: 20px;
      color: green;
    }
  }
  .chat-status {
    min-height: 49px;
    .chat-date {
      display: block;
      font-size: 10px;
      font-style: italic;
      color: #fff;
      text-shadow: 0px -1px 0px #222, 0px 1px 0px #aaa;
      height: 15px;
      left: 10%;
      right:10%;
    }
    .chat-content-center {
      padding: 5px 10px;
      background-color: #e1e1f7;
      border-radius: 6px;
      font-size: 12px;
      color: #555;
      height: 34px;
      left: 10%;
      right:10%;
    }
  }
  .chat-message {
    width: 80%;
    min-height: 40px;
    .right-bubble {
        position: relative;
        background: #dcf8c6;
        border-top-left-radius: .4em;
      border-bottom-left-radius: .4em;
      border-bottom-right-radius: .4em;
      padding: 5px 10px 10px;
      left: 15%;
      span.msg-name {
        font-size: 12px;
        font-weight: bold;
        color: green;
      }
      span.msg-date {
        font-size: 10px;
      }
    }

    .right-bubble:after {
        content: '';
        position: absolute;
        right: 0;
        top: 0;
        width: 0;
        height: 0;
        border: 27px solid transparent;
        border-left-color: #dcf8c6;
        border-right: 0;
        border-top: 0;
        margin-top: -13.5px;
        margin-right: -27px;
    }
    .left-bubble {
        position: relative;
        background: #ffffff;
      border-top-right-radius: .4em;
      border-bottom-left-radius: .4em;
      border-bottom-right-radius: .4em;
      padding: 5px 10px 10px;
      left: 5%;
      span.msg-name {
        font-size: 12px;
        font-weight: bold;
        color: blue;
      }
      span.msg-date {
        font-size: 10px;
      }
    }

    .left-bubble:after {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        width: 0;
        height: 0;
        border: 27px solid transparent;
        border-right-color: #ffffff;
        border-left: 0;
        border-top: 0;
        margin-top: -13.5px;
        margin-left: -27px;
    }
  }
}


Run the Ionic Angular Firebase Chat App on The Devices

This time to run the Ionic 3, Angular 5 and Firebase Chat app on the real devices. Before that remove/add the Cordova platform first.

ionic cordova platform rm ios
ionic cordova platform add ios
ionic cordova platform rm android
ionic cordova platform add android

Now, run to the device by type this command.

ionic cordova run android

or

ionic cordova run ios

Then you will see the Ionic 3, Angular 5 and Firebase chat app like below.

Build Ionic 3, Angular 5 and Firebase Simple Chat App - Chat result

That's it, the simple Ionic 3, Angular 5, Cordova and Firebase chat app. If there are any missing steps in this tutorial you can compare with the working source codes on our GitHub.

We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 4 - Full Starter App and save development and design time. Android, iOS, and PWA, 100+ Screens and Components, the most complete and advance Ionic Template.

That just the basic. If you need more deep learning about Ionic, Angular, and Typescript, you can take the following cheap course:

Thanks!