Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App

by Didin J. on Jan 10, 2024 Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App

A comprehensive step-by-step tutorial on Ionic-Angular Firebase Realtime Database to create-read-update-delete (CRUD) simple example

Ionic-Angular and Firebase are great combinations for mobile app development. Firebase gives you functionality like analytics, databases, messaging, and crash reporting so you can move quickly and focus on your users. Ionic-Angular as mobile apps and Firebase as data storage, it's all connected using the Firebase library for Angular. So you don't need servers to build your Ionic-Angular app.

This tutorial is divided into several steps:

What we built here is just the Ionic-Angular and Firebase CRUD app for the Bulletin Board which just creates information and then shows the list of information on the home page of the app. There are also details of information, edit and delete the bulletin board information. At the end, we will build this Ionic-Angular app for iOS and Android using Capacitor. The following tools, frameworks, and modules are required for this tutorial:

  1. Node.js
  2. Ionic-CLI
  3. Angular
  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. To check it, type this command in the terminal or Node.js command line.

node -v
v20.8.0
npm -v
10.2.0
ionic -v
7.1.1

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

npm uninstall -g ionic
npm install -g @ionic/cli
ionic -v
7.2.0

Let's get started on the main step!


Step #1: Setup Google Firebase

Open your browser, go to console.firebase.google.com, and log in using your Google account.

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - firebase-console

Click the "+" Add Project button then name it as you like (ours: BulletinBoard) then click the Continue button. Leave it as default then click the Continue button again. Select the Google Analytics account then click the Create Project button.

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - project done

Now, the Firebase project is ready then click the Continue button.

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - firebase-dashboard

Go to the Build menu, choose the Realtime Database then click the Create Database button. Choose the Realtime Database location then click the Next button. 

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - setup db

Choose start in test mode then click the Enable button. Now, the Firebase Real-time Database is ready to use. Don't close the Firebase console because we will need configuration later on the Ionic application.


Step #2: Create a New Ionic Angular App

To create a new Ionic-Angular app, type this command.

ionic start ionic-firebase-crud blank --type=angular

Choose the NgModules then click Enter.

? Would you like to build your app with NgModules or Standalone Components? 
 Standalone components are a new way to build with Angular that simplifies the w
ay you build your app. 
 To learn more, visit the Angular docs:
 https://angular.io/guide/standalone-components

 (Use arrow keys)
❯ NgModules 
  Standalone 

Now, wait for the Ionic application to create and install all dependencies including the Capacitor module. Next, leave all question answers as default to finish the Ionic Project creation. Next, go to the newly created app folder.

cd ./ionic-firebase-crud

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

ionic serve

The Ionic application shows as the full screen of the browser, to show as a Mobile app in the browser, right-click then click inspect. Choose the Toggle Device toolbar or click the Command + Shift + M keys together.

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - ionic serve

To stop the running Ionic application, press the CTRL+C keys.


Step #3: Install and Configure the Firebase Module

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

npm install --save firebase

Next, open your Ionic project using your IDE or Text Editor.

code .

Next, register the Firebase module in the Ionic-Angular app by opening and editing this src/app.component.ts file and then adding this import of Firebase.

import { initializeApp } from 'firebase/app';

Next, create a constant variable after the imports to configure the Firebase.

const firebaseConfig = {
  apiKey: 'FIREBASE_WEB_APIKEY',
  databaseURL: 'https://FIREBASE_PROJECT_ID.firebaseio.com',
};

You can fight the Firebase configuration parameters in the Firebase Settings. Back to the Firebase console, click the Gear button and Project Settings. If there's no web API key, click the </> button to add the web app. Just follow the wizard for the web app creation, at the end you will find all Firebase configuration parameters. 

Next, inside the constructor, add these lines of the Typescript code to initialize the Firebase real-time database.

  constructor() {
    initializeApp(firebaseConfig);
  }

Now, the Firebase database is ready to populate.


Step #4: Add a List of Bulletin Board

We will use the existing Ionic-Angular home page to display the list on the bulletin board. Open and edit src/app/home/home.page.ts then add these imports of AlertController (@ionic/angular), Router, ActivatedRoute (@angular/router), and Firebase.

import { AlertController, LoadingController } from '@ionic/angular';
import { Router } from '@angular/router';
import { getDatabase, onValue, ref, remove } from "firebase/database";

Declare constant variables after the imports to initialize the Firebase database.

const db = getDatabase();
const dbRef = ref(db, 'infos/');

Declare variables before the constructor to hold the bulletin board list and reference the Firebase database.

  infos: any[] = [];

Add this Firebase function to listen to any value changes from the Firebase Database then extract the response to an array using the next function. Also, initialize the Ionic Alert Controller and the Loading Controller inside the constructor parameters.

  constructor(private router: Router, private loadingController: LoadingController, private alertController: AlertController) {
    onValue(dbRef, (snapshot) => {
      this.infos = [];
      snapshot.forEach((childSnapshot) => {
        this.infos.push({
          id: childSnapshot.key,
          info_title: childSnapshot.val().info_title,
          info_description: childSnapshot.val().info_description
        });
      });
    }, {
      onlyOnce: false
    });
  }

Add a function under the constructor for navigating to the add-info page.

  addInfo() {
    this.router.navigate(['/add-info']);
  }

Add a function for editing info data.

  edit(id: string) {
    this.router.navigate(['/edit', { id: id }]);
  }

Add an asynchronous function for deleting info data.

  async delete(id: string) {
    const alert = await this.alertController.create({
      header: 'Confirm!',
      message: 'Are you sure want to delete this info?',
      buttons: [
        {
          text: 'Cancel',
          role: 'cancel',
          cssClass: 'secondary',
          handler: (blah) => {
            console.log('cancel');
          }
        }, {
          text: 'Okay',
          handler: () => {
            const deleteRef = ref(db, 'infos/' + id);
            remove(deleteRef);
          }
        }
      ]
    });

    await alert.present();
  }

Finally, open and edit src/app/home/home.page.html then replace all tags with this <ion-content> that contain <ion-list> with an array of data.

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Info List
    </ion-title>
    <ion-buttons slot="end">
      <ion-button routerLink="/create"><ion-icon name="add-circle"></ion-icon></ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item-sliding *ngFor="let info of infos">
      <ion-item detail lines="full" [routerLink]="['/detail', { id: info.id }]">
        <ion-icon name="desktop" slot="start"></ion-icon>
        {{info.info_title}}
      </ion-item>
      <ion-item-options side="end">
        <ion-item-option color="primary" (click)="edit(info.id)">EDIT</ion-item-option>
        <ion-item-option color="danger" (click)="delete(info.id)">DELETE</ion-item-option>
      </ion-item-options>
    </ion-item-sliding>
  </ion-list>
</ion-content>


Step #5: Add Page for Create Bulletin Board Info

To create a new Ionic-Angular page, we use Ionic CLI to generate it. Type this command to generate it.

ionic g page create

Next, open and edit src/app/create/create.module.ts then add or modify this import to add ReactiveFormsModule.

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

Add this ReactiveFormsModule to the @NgModule imports.

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    CreatePageRoutingModule,
    ReactiveFormsModule
  ],
  declarations: [CreatePage]
})

We will need an ID for each created Firebase database data. For that, we will use UUID by installing the UUID module.

npm i --save uuid
npm i --save @types/uuid

Next, open and edit src/app/create/create.page.ts then add these imports of UUID, ActivatedRoute, Router, FormControl, FormGroupDirective, FormBuilder, NgForm, Validators, and FormArray (Angular Forms).

import { getDatabase, ref, set } from "firebase/database";
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, Validators } from '@angular/forms';
import { v4 as uuidv4 } from 'uuid';

Inject those modules to the constructor params.

  constructor(
    private router: Router,
    private formBuilder: FormBuilder
  ) { }

Add these constant variables after the imports.

const db = getDatabase();

Add this variable before the constructor to initialize the Angular FormGroup.

  infoForm = this.formBuilder.group({
    info_title: [null, Validators.required],
    info_description: [null, Validators.required]
  });

Next, add the function to post the form data to the Firebase Real-time Database.

  saveInfo() {
    const id = uuidv4();
    set(ref(db, 'infos/' + id), this.infoForm?.value).then((newInfo: any) => {
      this.router.navigate(['/detail', { id: id }]);
    })
  }

Finally, open and edit src/app/create/create.page.html then replace all HTML tags with this.

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Create Info</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <form [formGroup]="infoForm">
    <ion-item>
      <ion-input type="text" label="Info Title" labelPlacement="floating" formControlName="info_title"></ion-input>
    </ion-item>
    <ion-item>
      <ion-input type="text" label="Info Description" labelPlacement="floating" formControlName="info_description"></ion-input>
    </ion-item>
    <ion-button shape="round" color="primary" expand="block" [disabled]="!infoForm.valid"
      (click)="saveInfo()">Save</ion-button>
  </form>
</ion-content>


Step #6: Add Page for Show Bulletin Board Info Detail

Please create a new Ionic-Angular page by typing this command to generate it.

ionic g page detail

Open and edit src/app/detail/detail.page.ts then add these imports of Firebase, ActivatedRoute, and Router.

import { ActivatedRoute, Router } from '@angular/router';
import { DataSnapshot, getDatabase, onValue, ref } from "firebase/database";

Inject those modules into the constructor.

  constructor(
    private route: ActivatedRoute,
    public router: Router
  ) { }

Add a constant variable after the imports to initialize the Firebase database.

const db = getDatabase();

Declare a variable before the constructor.

info: any = {};

Load info data from the Firebase Realtime Database to the body of the constructor.

  constructor(
    private route: ActivatedRoute,
    public router: Router
  ) {
    const infoRef = ref(db, 'infos/' + this.route.snapshot.paramMap.get('id'));
    onValue(infoRef, (snapshot) => {
      const data = snapshot.val();
      this.info = snapshotToObject(snapshot);
    });
  }

Create this class for converting Firebase Real-time Database response to the Angular object.

export const snapshotToObject = (snapshot: DataSnapshot) => {
  let item = snapshot.val();
  item.key = snapshot.key;

  return item;
}

Finally, open and edit src/app/detail/detail.page.html then replace all HTML tags with this.

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Info Details</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <ion-card>
    <ion-card-content>
      <ion-card-title>{{info.info_title}}</ion-card-title>

      <p>{{info.info_description}}</p>
    </ion-card-content>
  </ion-card>
</ion-content>


Step #7: Add Page for Edit Bulletin Board Info

Please create a new Ionic-Angular page by typing this command to generate it.

ionic g page edit

Next, open and edit src/app/edit/edit.module.ts then add or modify this import to add ReactiveFormsModule.

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

Add this ReactiveFormsModule to the @NgModule imports.

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    EditPageRoutingModule,
    ReactiveFormsModule
  ],
  declarations: [EditPage]
})

Open and edit src/app/edit/edit.page.ts then add these imports of the required Angular Router and Forms.

import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, Validators } from '@angular/forms';
import { DataSnapshot, getDatabase, onValue, ref, set } from "firebase/database";

Inject those modules into the constructor.

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private formBuilder: FormBuilder
  ) { }

Add a constant variable after the imports to initialize the Firebase database.

const db = getDatabase();

Declare a variable to initialize the Angular FormGroup.

  infoForm = this.formBuilder.group({
    info_title: [null, Validators.required],
    info_description: [null, Validators.required]
  });

Create a function for loading info data based on the key that gets from params.

  getInfo() {
    const infoRef = ref(db, 'infos/' + this.route.snapshot.paramMap.get('id'));
    onValue(infoRef, (snapshot) => {
      this.info = snapshotToObject(snapshot);
      this.infoForm.controls['info_title'].setValue(this.info.info_title);
      this.infoForm.controls['info_description'].setValue(this.info.info_description);
    });
  }

Call that function to the body of the constructor.

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private formBuilder: FormBuilder
  ) {
    this.getInfo();
  }

Create this class for converting Firebase Real-time Database response to the Angular object.

export const snapshotToObject = (snapshot: DataSnapshot) => {
  let item = snapshot.val();
  item.key = snapshot.key;

  return item;
}

Add this function to update the data from the FormGroup to the Firebase Real-time Database.

  updateInfo() {
    set(ref(db, 'infos/' + this.route.snapshot.paramMap.get('id')), this.infoForm.value)
      .then(() => {
        this.router.navigate(['/detail', { id: this.route.snapshot.paramMap.get('id') }]);
      })
      .catch((error) => {
        console.log(error);
      });
  }

Finally, open and edit src/app/edit/edit.page.html then replace all HTML tags with this.

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Edit Info</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <form [formGroup]="infoForm">
    <ion-item>
      <ion-input type="text" label="Info Title" labelPlacement="floating" formControlName="info_title"></ion-input>
    </ion-item>
    <ion-item>
      <ion-input type="text" label="Info Description" labelPlacement="floating" formControlName="info_description"></ion-input>
    </ion-item>
    <ion-button shape="round" color="primary" expand="block" [disabled]="!infoForm.valid"
      (click)="updateInfo()">Update</ion-button>
  </form>
</ion-content>


Step #8: Run and Test the Ionic-Angular and Firebase Realtime App

This is the time to show what we have built in the Ionic-Angular and Firebase CRUD mobile apps. Now, we have to add a platform for Android and iOS.

ionic capacitor add android 
ionic capacitor add ios

Next, type this command to build an Android app and start Android Studio.

ionic capacitor build android

Choose the simulator device then click the play button to run the Android app to the simulator. For the iOS, type this command to build it. 

ionic capacitor build ios

Choose the simulator device then click the play button to run the iOS app to the simulator. For the iOS, type this command to build it. Here they look like. 

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - demo 1

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - demo 2

If you go back to the Firebase console. The data structure will be like this.

Ionic Angular Tutorial: Firebase Realtime CRUD Mobile App - data structure

That it's, the Ionic-Angular and Firebase Realtime Database CRUD mobile apps. You can get the working full source code on our GitHub.

We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 6 - 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!