Ionic 5|4 CRUD Operations Using Firebase with Firestore NoSQL Database Tutorial in Ionic Angular Application

In this Ionic 5 tutorial, we’ll integrate Google’s Firebase and use NoSQL database service Firestore to perform CRUD operation by creating a Student Resister application.

The Firestore is a cloud-based Realtime NoSQL database service provided by Firebase. We’ll integrate Firestore services in an Ionic application and build a Student Register application and perform CRUD (Create, Read, Update and Delete) operations.

In a traditional SQL based Relational Database Management system works with Tables and Rows, but in a NoSQL database like Firestore, we work with Collections and Documents. In a NoSQL, database information is saved and fetched in the form of JSON objects.

The Student Register application which we are going to create will have a form using which we’ll add a new document for each student having Name, Age and Address in the collection of Students. We’ll also add update, list and delete operation on Student collection.

 

Let’s begin…

 

Also See: How to Implement Firestore CRUD Operation in Angular 7/6 Application

# Update Ionic CLI

Run following npm command to update the Ionic CLI tool to the latest version

$ npm install -g @ionic/cli

 

# Create new Ionic application:

Execute the following command to create a new Ionic Angular application with a blank template:

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

then move to the root path of the application

$ cd ionic-firebase-crud-operations

# Create a Firebase Project

If you already having any Firebase project, you can use that or follow these steps to create one and enable Firestore database. After creating a Firebase project we will use credentials in our Ionic Application.

 

Step 1) Visit Firebase here then click on Get Started if you have not created an account yet.

 

Step 2) Click on "Add project" then enter app-related information click on "Create project"

 

Step 3) Next click on "Web App" icon to get configuration text with app secret info which we will add in our Ionic Application to communicate with services related to this Firebase project.

 

Step 4) Then enable Firestore Database service in your Firebase project.

On the left sidebar select Database, then click on the Create button. This will enable the Database service for our Firebase application. Now we are ready to connect our Ionic application with this Firebase application.

# Adding Firebase Credentials in Ionic 5 Application

Now we need to add the Firebase application credential in the Ionic application to create a connection. Open the Environment file at location "~ionic-firebase-crud-operations/src/environments/environment.ts" then update it with your credential as shown below:

export const environment = {
  production: false,
  firebase: {
    apiKey: "[YOUR_apiKey_HERE]",
    authDomain: "[YOUR_authDomain_HERE]",
    databaseURL: "[YOUR_databaseURL_HERE]",
    projectId: "[YOUR_projectId_HERE]",
    storageBucket: "[YOUR_storageBucket_HERE]",
    messagingSenderId: "[YOUR_messagingSenderId_HERE]",
    appId: "[YOUR_appId_HERE]"
  }
};

# Install Firebase in Application

To integrate Firebase services, we'll install angularfire package in the Ionic Angular application. It is a Firebase official package for Angular applications. This package lets an Angular project to use all Firebase services.

As a dependency, we also need to install the firebase package which will work under the hood with angularfire.

Install these packages by running following npm command in the terminal window

$ npm install firebase @angular/fire --save

 

# Import Firebase Modules

We need to import the required AngularFireModule and also the AngularFirestoreModule to use the Firestore NoSQL database service.

To create a connection between Firebase application with Ionic Angular application, we will use the AngularFireModule's initializeApp method to take environment.firebase credentials.

After making above changes the app.module.ts file will look like this

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { environment } from 'src/environments/environment';

import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';


@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,

    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

by following above steps your application is connected with Firebase and ready to perform CRUD operation on Firestore Database.

 

# Create a Service with Firestore CRUD methods

Now we'll create a new service to perform CRUD operation by using methods available in the AngularFirestore class.

Run the following ionic generate command to create firebaseService in the services folder in the Ionic application.

$ ionic generate service services/firebase

 

# Update the FirebaseService with CRUD methods

After creating the service at location "~ionic-firebase-crud-operations/src/app/service/firebase.service.ts", update it with CRUD methods

Replace below code in the firebase.service.ts file
// firebase.service.ts
import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';

@Injectable({
  providedIn: 'root'
})
export class FirebaseService {

  collectionName = 'Students';

  constructor(
    private firestore: AngularFirestore
  ) { }

  create_student(record) {
    return this.firestore.collection(this.collectionName).add(record);
  }

  read_students() {
    return this.firestore.collection(this.collectionName).snapshotChanges();
  }

  update_student(recordID, record) {
    this.firestore.doc(this.collectionName + '/' + recordID).update(record);
  }

  delete_student(record_id) {
    this.firestore.doc(this.collectionName + '/' + record_id).delete();
  }
}
In the above service, import the AngularFirestore class to use its methods. Following are the methods doing operations on Students collection and manipulating the documents.
create_student(): Create a new record in the specified collection by calling the add() method
read_students(): Call snapshotChanges() method which will get records and also subscribe it to get updates
update_student(): The doc() method takes collection name with document id to update the record, then the update() method is called to save the document.
delete_student(): Like update the doc() method takes collection name with id to delete() the document.

 

# Update User Interface in the Home Page

The final step is to create a page for User Interaction where we can create a new record and can view all rows available in the collection.

A user can also click on Edit and Delete buttons to perform record actions. In edit mode, the user can Cancel or Update changes.

To keep tutorial simple we will update existing home component which is created by default in blank Ionic 4 template.

# Add Student Form and List

We have a form with [formGroup] for reactive form validation and (ngSubmit) event handler. There are three input controls for Name, Age and Address having formControlName property on each to get value and validation.

The list of Students is shown in the ion-card component. This is having conditional blocks for Edit mode.

<ion-header [translucent]="true">
  <ion-toolbar color="warning">
    <ion-title>
      Student Register
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true" class="ion-padding">

  <form [formGroup]="studentForm" (ngSubmit)="CreateRecord()">

    <ion-item>
      <ion-label position="floating">Name</ion-label>
      <ion-input formControlName="Name"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label position="floating">Age</ion-label>
      <ion-input formControlName="Age"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label position="floating">Address</ion-label>
      <ion-input formControlName="Address"></ion-input>
    </ion-item>

    <ion-item>
      <ion-button (click)="CreateRecord()" [disabled]="studentForm.invalid">
        <ion-icon size="small" slot="icon-only" name="add"></ion-icon>
        &nbsp;Create Record
      </ion-button>
    </ion-item>

  </form>


  <ion-card *ngFor="let item of studentList" color="primary">
    <span *ngIf="!item.isEdit; else elseBlock">
      <ion-card-header>
        <ion-card-title>{{item.Name}} of {{item.Age}} years</ion-card-title>
        <ion-card-subtitle>From: {{item.Address}}</ion-card-subtitle>
      </ion-card-header>
      <ion-card-content>

        <ion-button shape="round" color="secondary" size="small" (click)="EditRecord(item)">
          <ion-icon size="small" slot="icon-only" name="create"></ion-icon>

        </ion-button>
        <ion-button shape="round" color="danger" size="small" (click)="RemoveRecord(item.id)">
          <ion-icon size="small" slot="icon-only" name="trash"></ion-icon>

        </ion-button>
      </ion-card-content>
    </span>
    <ng-template #elseBlock>
      <ion-card-header>
        <ion-card-title>
          <ion-grid>
            <ion-row>
              <ion-col>
                Edit
              </ion-col>
              <ion-col>
                <ion-button fill="solid" color="medium" size="small" (click)="item.isEdit = false">
                  Cancel
                </ion-button>
              </ion-col>
              <ion-col>
                <ion-button fill="solid" color="success" size="small" (click)="UpdateRecord(item)">
                  Update
                </ion-button>
              </ion-col>
            </ion-row>
          </ion-grid>
        </ion-card-title>
      </ion-card-header>
      <ion-card-content>
        <ion-item>
          <ion-label><strong>Name</strong></ion-label>
          <ion-input type="text" [(ngModel)]="item.EditName"></ion-input>
        </ion-item>
        <ion-item>
          <ion-label><strong>Age</strong></ion-label>
          <ion-input type="text" [(ngModel)]="item.EditAge"></ion-input>
        </ion-item>
        <ion-item>
          <ion-label><strong>Address</strong></ion-label>
          <ion-input type="text" [(ngModel)]="item.EditAddress"></ion-input>
        </ion-item>
      </ion-card-content>
    </ng-template>
  </ion-card>

</ion-content>

 

 

 

# Update Home Class

Replace following code in the home.page.ts file

// home.page.ts
import { Component } from '@angular/core';
import { FirebaseService } from '../services/firebase.service';
import { FormGroup, Validators, FormBuilder } from '@angular/forms';

interface StudentData {
  Name: string;
  Age: number;
  Address: string;
}

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  studentList = [];
  studentData: StudentData;
  studentForm: FormGroup;

  constructor(
    private firebaseService: FirebaseService,
    public fb: FormBuilder
  ) {
    this.studentData = {} as StudentData;
  }

  ngOnInit() {

    this.studentForm = this.fb.group({
      Name: ['', [Validators.required]],
      Age: ['', [Validators.required]],
      Address: ['', [Validators.required]]
    })

    this.firebaseService.read_students().subscribe(data => {

      this.studentList = data.map(e => {
        return {
          id: e.payload.doc.id,
          isEdit: false,
          Name: e.payload.doc.data()['Name'],
          Age: e.payload.doc.data()['Age'],
          Address: e.payload.doc.data()['Address'],
        };
      })
      console.log(this.studentList);

    });
  }

  CreateRecord() {
    console.log(this.studentForm.value);
    this.firebaseService.create_student(this.studentForm.value).then(resp => {
      this.studentForm.reset();
    })
      .catch(error => {
        console.log(error);
      });
  }

  RemoveRecord(rowID) {
    this.firebaseService.delete_student(rowID);
  }

  EditRecord(record) {
    record.isEdit = true;
    record.EditName = record.Name;
    record.EditAge = record.Age;
    record.EditAddress = record.Address;
  }

  UpdateRecord(recordRow) {
    let record = {};
    record['Name'] = recordRow.EditName;
    record['Age'] = recordRow.EditAge;
    record['Address'] = recordRow.EditAddress;
    this.firebaseService.update_student(recordRow.id, record);
    recordRow.isEdit = false;
  }

}

First, we have initialized the Form with FormGroup.

studentForm: FormGroup;

 

The data will be of interface type StudentData defined in the class.

interface StudentData {
  Name: string;
  Age: number;
  Address: string;
}

 

Then create a group of the form using FormBuilder class method and define required validation.

    this.studentForm = this.fb.group({
      Name: ['', [Validators.required]],
      Age: ['', [Validators.required]],
      Address: ['', [Validators.required]]
    })

 

On page init, we will call the read_student() service method to fetch the existing list of items saved in the Firestore collection and subscribe to them. So whenever there will be a change in the Firestore data during CRUD operations, the changes will be updated in real-time as we called the snapshotChanges() method on the Students collection.

    this.firebaseService.read_students().subscribe(data => {

      this.studentList = data.map(e => {
        return {
          id: e.payload.doc.id,
          isEdit: false,
          Name: e.payload.doc.data()['Name'],
          Age: e.payload.doc.data()['Age'],
          Address: e.payload.doc.data()['Address'],
        };
      })

    });

The CreateRecord() method will take form values to submit to the Forestore by calling the create_student() service method. On success, we are resetting the form.

  CreateRecord() {
    this.firebaseService.create_student(this.studentForm.value)
      .then(resp => {
        //Reset form
        this.studentForm.reset();
      })
      .catch(error => {
        console.log(error);
      });
  }

On clicking the Edit icon we are setting the actual values in temporary fields using the EditRecord() method so that we can show actual values if the user clicks the cancel button

  EditRecord(record) {
    record.isEdit = true;
    record.EditName = record.Name;
    record.EditAge = record.Age;
    record.EditAddress = record.Address;
  }

On hitting the update button in edit mode the changed values will be updated by calling the update_student() method in service.

  UpdateRecord(recordRow) {
    let record = {};
    record['Name'] = recordRow.EditName;
    record['Age'] = recordRow.EditAge;
    record['Address'] = recordRow.EditAddress;
    this.firebaseService.update_student(recordRow.id, record);
    recordRow.isEdit = false;
  }

 

# Import ReactiveFormModule for FormValidation

As we are using Reactive Form approach for validating the form for creating Student, we need to import the ReactiveFormsModule in the home.module.ts file as shown below:

// home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HomePage } from './home.page';

import { HomePageRoutingModule } from './home-routing.module';


@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule,
    HomePageRoutingModule
  ],
  declarations: [HomePage]
})
export class HomePageModule { }

 

That's it now you can run the application in your browser by running

$ ionic serve --open

 

Get source code of this tutorial in GitHub repo here.

 

Conclusion: We discussed on how we can integrate Firebase service in Ionic Angular application. We used the Firestore to perform CRUD operation using NoSQL real-time database service to create a Students register here. You can use any service in a similar way like Authentication of users by Email and Password.

Subscribe
Notify of
17 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Tyvm, the only tutorial that really worked for me !!!!!

Thank You so Much!!!!!!!!!

hi, thank you for this post. i managed to follow this tutorial and it works! But how to make the user that login just view their post?

Thanks you very much !!
It works perfectly and it is well explained

Great job 🙂

CreateRecord() {
let record = {};
record[‘Name’] = this.studentName;
record[‘Age’] = this.studentAge;
record[‘Address’] = this.studentAddress;
this.crudService.create_NewStudent(record).then(resp => {
this.studentName = “”;
this.studentAge = undefined;
this.studentAddress = “”;
console.log(resp);
})

encounted an error with then.
Property ‘then’ does not exist on type ‘void’.

Great tutorial!

By the way, I am getting the below error.
“FirebaseError: Missing or insufficient permissions”

I am newbie on Ionic, so I’d like to get your help.

Great tutorial, how would we go about making a separate page for adding a student, and then another page to view the added students?

Thanks