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
// 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();
}
}
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()
methodread_students()
: Call snapshotChanges()
method which will get records and also subscribe it to get updatesupdate_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>
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.
one an only working tutorial
but these codes are missing some codes.
//in 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 { AppComponent } from ‘./app.component’;
import { AppRoutingModule } from ‘./app-routing.module’;
import { initializeApp, provideFirebaseApp } from ‘@angular/fire/app’;
import { environment } from ‘../environments/environment’;
import { provideAuth, getAuth } from ‘@angular/fire/auth’;
import { provideDatabase, getDatabase } from ‘@angular/fire/database’;
import { AngularFireModule } from “@angular/fire/compat”;
import { AngularFireAuthModule } from “@angular/fire/compat/auth”;
import { AngularFireStorageModule } from ‘@angular/fire/compat/storage’;
import { AngularFirestoreModule } from ‘@angular/fire/compat/firestore’;
import { AngularFireDatabaseModule } from ‘@angular/fire/compat/database’;
import ‘firebase/storage’;
import { FormsModule } from ‘@angular/forms’;
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), FormsModule,
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFirestoreModule,
AngularFireAuthModule,
AngularFireStorageModule,
AngularFireDatabaseModule],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
export class AppModule {}