Ionic firebase CRUD operation in Details

In this article, we’ll explore how to implement CRUD operation in the Ionic firebase project. Firebase is serverless technology from Google. We can consider it as Backend as a service that offers a wide range of services such as hosting, real-time databases, and cloud functions. We can use Firebase to store/manipulate data. With Ionic Firebase we can easily do CRUD and it provides login with a different authentication option.

In this article, we’ll explore details on how to configure and implement the Ionic firebase project with an example of all CRUD operations. We two main goals behind this tutorial, first, we will see how we can configure the firebase project from scratch and understand second we’ll learn CRUD operation on our Ionic firebase using the angularFire library. Let’s get started.

Setting up an Ionic Firebase example

With the release of ionic version 4, the Ionic framework no longer limited to angular. We can create ionic projects in different front-end frameworks like Angular, Vue, and React. Let first create a blank Ionic Angular project for our ionic firestore example and add angularFire and firebase libraries to implement ionic firebase CRUD operation.

ionic start firebaseAuth blank --type=angular
npm install firebase --save
ng add @angular/fire

The above command will create and install firebase and angular/fire libraries in our Ionic Angular project. The AngularFire is an official library for Angular to support Firebase functionalities. AngularFire provide us lot of support like observable, real-time bindings, authentication, and offline data support.

Here is a screenshot of our Ionic firestore CRUD operation.

Ionic firebase CRUD example

Create and configure our project in the Firebase console.

Now we need to create and configure our serverless backend firebase project and let login to your firebase site simply click Add project, as shown in Figure 1.

Ionic firebase example

In the Firebase console, we need to click on Add Project to create a new project and we should give the name of our project, In our case say quote as a project name.

Ionic firestore example

We can see that we have given our project name as the quote and then click on continue. Firebase console will ask you to change Cloud Firestore location based on your location; however, the default setting should be enough to get started. Once we complete the above step, the firebase console will take us to our new project dashboard. You will see the following option in the dashboard and let’s click on the web.

Firebase provides three options, IOS, Android, and web, we are creating a web-based project Ionic firebase example, it will work perfectly for the Ionic mobile or PWA application. When we click on it, we will ask to register the app and given an app nickname, for our example, we name our app nickname as a quote and we need to click on the register app.

Once we click on register it will show our firebase configuration APIkey for our project like this.

firebaseConfig = {
    apiKey: "A...............................s",
    authDomain: "quotesite-b.....firebaseapp.com",
    databaseURL: "https://quotesite-b1....firebaseio.com",
    projectId: "quotesite-b..e",
    storageBucket: "quotesite-b..e.appspot.com",
    messagingSenderId: "7827103245198",
    appId: "1:203541...81105:web:sddgebbb18esdv34c7e575bd0"
}

We need to copy this our firebase project APIkey, above is just for demo and let copy your project API key from firebase project console and past it in our client project ssrc/environments/environment.ts as shown in the code snippet below.

export const environment = {
  production: false,
  firebaseConfig: {
    apiKey: "A...............................s",
    authDomain: "quotesite-b.....firebaseapp.com",
    databaseURL: "https://quotesite-b1....firebaseio.com",
    projectId: "quotesite-b..e",
    storageBucket: "quotesite-b..e.appspot.com",
    messagingSenderId: "7827103245198",
    appId: "1:203541...81105:web:sddgebbb18esdv34c7e575bd0"
  }
};

Create cloud firestore databse

We have almost finished our firebase project configure in firebase.com, now we need to create our firebase database. Lets click on firestore database icon as show below.

Click on creare database will ask us for production or test mode and this is an example. Let select test mode, now our database is ready. In later articles we will learn how add authenication and authorization on our Ionic firebase example.

Import AngularFireModule and its configuration in app.module.ts

In our ser/environments/environment.ts file, we have our firebase API configuration information and we need to add this data our angularFireModule in app.module.ts file. Add the following code in app.module.ts file.

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 { AngularFireModule } from '@angular/fire';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebaseConfig)
  ],
  providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
  bootstrap: [AppComponent],
})
export class AppModule { }

Create quote service to implement CRUD operation

It good coding practice to keep database operation separate from ionic component, let create a quote service to implement our logic.

ionic generate service services/quote

By running above code will create folder services and add file called quote.service.ts file. In this file we are accessing our firebase database which is called collection in firebase firestore database. Edit quote.service.ts file.

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { IQuote } from '../models/quote';

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

  constructor(private db: AngularFirestore) { }

  createQuote(quote: IQuote) {
    const quoteData = JSON.parse(JSON.stringify(quote));
    return this.db.collection('quotes').add(quoteData);
  }

  getAllQuotes(): Observable<IQuote[]> {
    const quotes = this.db.collection<IQuote>('quotes').snapshotChanges().pipe(
      map(actions => {
        return actions.map(
          c => ({
            postId: c.payload.doc.id,
            ...c.payload.doc.data()
          }));
      }));
    return quotes;
  }

  getQuotebyId(id: string): Observable<IQuote> {
    const quoteDetails = this.db.doc<IQuote>('quotes/' + id).valueChanges();
    return quoteDetails;
  }

  updateQuote(quoteId: string, quote: IQuote) {
    return this.db.doc('quotes/' + quoteId).update(JSON.parse(JSON.stringify(quote)));
  }

  deleteQuote(quoteId: string) {
    return this.db.doc('quotes/' + quoteId).delete();
  }
}

In service we have reference to our collection, in our case, quotes is a collection name that links to our firebase collection database. The create method will accept a parameter of type IQuote. We will parse the parameter to a JSON object and add it to the ‘quotes’ collection in our database. If the collection already exists then a new quote JSON is added to collections quotes. However, if collections don’t exist then create method will create new collections called quotes and add quote data on them. The delete and update methods need the id of data from collection, in our case quote data have postId as id by default.

As we defined different methods like create, update or edit, delete and retrieve all data of types IQuote from our collection quotes. We also need to define a model called IQuote. Let create folder models in the src/app folder and add a file called quote.ts to define a model for our data that is quoted.

export interface IQuote {
    postId?: string;
    quoteText: string;
    by:  string;
}

Create components to add|edit and list Ionic firebase data

To implement the Ionic firebase CRUD operation, we will create a form that allows us to add/edit quotes containing quote text and quote by. All quote adding, deleting, editing, and listing are done in our quote service, which is consumed by component, we need a quote component to add a new quote or edit an existing quote. Which intern is Ionic firebase add or edit operation and let generate a quote and quote-detail component using Ionic CLI?

ionic generate component components/quote
ionic generate component components/quote-detail

Running this command will declare quote.component and quote-detail component in app.module.ts file, we need to remove it and will declare both components in a shared module which will have all our common component. In components the folder adds a file called shared.module.ts file adds the following code.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { QuoteDetailComponent } from '../components/quote-detail/quote-detail.component';
import { QuoteComponent } from './quote/quote.component';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    CommonModule,
    IonicModule,
    ReactiveFormsModule
  ],
  declarations: [QuoteComponent, QuoteDetailComponent],
  exports: [QuoteComponent, QuoteDetailComponent]
})
export class SharedModule {}

Here we have declared and export both our components in a shared module and we also need to import ReactiveFormModule as we need it for adding new or editing quotes using ionic reactive Form.

Let add Ionic form in quote component to add new | edit data for Ionic Firebase.

We have already created a quote component, here we define two operations and it can be either add or edit quotes. In our home.component.html we have add button to add a new quote. Let’s edit quote.component.ts file

We have defined and made our quote component as an Ionic modal, which will pop up on our home page to add or edit quotes. We have added our app screenshot image on starting of our article, quote component performs two activities.

  • Add a new quote when we click on the fab add button in the home template.
  • Edit existing quotes when we click on the edit button on each quote.

Let edit components/quote.component.html template to add form.

<ion-header>
  <ion-toolbar color="primary">
    <ion-title *ngIf="!quote">Add new quote</ion-title>
    <ion-title *ngIf="quote">Edit quote</ion-title>
    <ion-buttons slot="end">
      <ion-icon name="close" (click)="close()"></ion-icon>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content>
  <form [formGroup]="myForm" (ngSubmit)="edit(myForm.value)">
    <ion-list>
      <ion-item class="ion-margin-bottom">
        <ion-label position="floating">Enter Quote</ion-label>
        <ion-input type="text" formControlName="quoteText"></ion-input>
      </ion-item>

      <ion-item class="ion-margin-bottom">
        <ion-label position="floating">Quote By</ion-label>
        <ion-input type="text" formControlName="by"></ion-input>
      </ion-item>

      <ion-item class="ion-float-right" lines="none">
        <ion-button *ngIf="!quote" color="primary" type="submit"[disabled]="!myForm.valid">Add Quote</ion-button>
        <ion-button *ngIf="quote" color="primary" type="submit" [disabled]="!myForm.valid">Edit Quote</ion-button>
      </ion-item>
    </ion-list>
  </form>
</ion-content>

In our blog component template, we have a form and also a condition to check whether to add a new or edit quote, if we have a quote then it means we are editing an existing quote in our quote component modal. Now let edit our components/quote.component.ts file.

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ModalController, NavParams } from '@ionic/angular';
import { IQuote } from 'src/app/models/quote';
import { QuoteService } from 'src/app/services/quote.service';

@Component({
  selector: 'app-quote',
  templateUrl: './quote.component.html',
  styleUrls: ['./quote.component.scss'],
})
export class QuoteComponent implements OnInit {
  myForm: FormGroup;
  quote: IQuote;

  constructor(private fb: FormBuilder,
    private modalCtrl: ModalController,
    private navParams: NavParams,
    private quoteService: QuoteService) { }

  ngOnInit() {
    // Get quote for edit
    this.quote = this.navParams.get('quote');
    debugger
    if (this.quote) {
      this.myForm = this.fb.group({
        quoteText: [this.quote.quoteText, Validators.required],
        by: [this.quote.by, Validators.required]
      });
    } else {
      this.myForm = this.fb.group({
        quoteText: [null, Validators.required],
        by: [null, Validators.required]
      });
    }
  }

  edit(value: IQuote) {
    if (!this.quote) {
      // Add new quote
      this.quoteService.createQuote({ quoteText: value.quoteText, by: value.by }).then(
        () => {
          console.log('Quote add successful');
          this.modalCtrl.dismiss();
        });
    } else {
      this.quoteService.updateQuote(this.quote.postId, { quoteText: value.quoteText, by: value.by }).then(
        () => {
          console.log('Quote edit successful');
          this.modalCtrl.dismiss();
        });
    }
  }

  close(): void {
    this.modalCtrl.dismiss();
  }

}

Here in ngOnInit method we are checking if we have quote or not, for edit quote we get existing quote from list of quote by clicking on edit button. We have navParams to get quote from list for edit quote, however for new quote we don’t have quote. For edit method we are checking if is add or edit mode, for add mode we calling createQuote method from our quote service and for edit mode we are calling updateQuote method from quote service.

List date from Ionic firestore using quote-detail component

In quote-detail component we display detailed data from each quote, we get quote data from the home component. Let’s edit quote-details component typescript to get quote data from home using @Input decorator.

import { Component, Input, OnInit } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { IQuote } from 'src/app/models/quote';
import { QuoteService } from 'src/app/services/quote.service';
import { QuoteComponent } from '../quote/quote.component';

@Component({
  selector: 'app-quote-detail',
  templateUrl: './quote-detail.component.html',
  styleUrls: ['./quote-detail.component.scss'],
})
export class QuoteDetailComponent {
  @Input('quoteData') quote: IQuote;

  constructor(
    private modalCtrl: ModalController,
    private quoteService: QuoteService) { }

  async edit(): Promise<void> {
    const modal = await this.modalCtrl.create({
      component: QuoteComponent,
      cssClass: 'quote-modal',
      backdropDismiss: false,
      componentProps: { quote: this.quote }
    });

    modal.present();
  }

  delete(): void {
    this.quoteService.deleteQuote(this.quote.postId).then(
      () => {
        alert('Delete successful');
      }
    );
  }

}

Here in quote-detail component we perfom following task.

  • Display detail data from each quote.
  • We had edit button to edit quote, which will take us to quote component for edit quote using Ionic modal which we have already discussed.
  • Delete button in quote-detail to delete quote.

Edit components/quote-detail/quote.detail.component.html template to display detail of each quote.

<ion-card>
  <ion-card-header color="danger"></ion-card-header>
  <ion-card-content> {{ quote.quoteText }}</ion-card-content>
  <ion-footer>
    <ion-row>
      <ion-col size="10">{{ quote.by }}</ion-col>
      <ion-col size="1">
        <ion-icon name="trash" (click)="delete()" color="danger"></ion-icon>
      </ion-col>
      <ion-col size="1">
        <ion-button size="small" fill="outline" (click)="edit()">Edit</ion-button>
      </ion-col>
    </ion-row>
  </ion-footer>
</ion-card>

Edit home page to iterate our Ionic firestore collection data

We have already complete adding, editing, and display detailed data from each quote, now we need to get a list of all data from collection quotes. On the home page we two main tasks.

  • Add button to take us to quote component to add a new quote.
  • Get all data from quotes collection and iterate through each and pass each quote to the quote-detail component to display.

Edit home.page.ts file for above activities.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { QuoteComponent } from '../components/quote/quote.component';
import { IQuote } from '../models/quote';
import { QuoteService } from '../services/quote.service';

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

  private unsubscribe$ = new Subject<void>();
  
  constructor(private modalCtrl: ModalController, private quoteService: QuoteService)  { }

  ngOnInit() {
    this.quoteService.getAllQuotes()
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(result => {
        this.quotes = result;
      });
  }

  async addQuote() {
    const modal = await this.modalCtrl.create({
      component: QuoteComponent,
      cssClass: 'quote-modal',
      backdropDismiss: false,
    });

    modal.present();
  }

  ngOnDestroy() {
    this.unsubscribe$.unsubscribe();
  }

}

Here in ngOnInit method, we have used getAllQuote from quote service to get all quotes from collection quote. Edit home.page.html template.

<ion-header [translucent]="true">
  <ion-toolbar color="primary">
    <ion-title>
      Ionic firebase CRUD operation on firestore
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <app-quote-detail *ngFor="let quote of quotes" [quoteData]="quote"></app-quote-detail>

  <ion-fab vertical="bottom" horizontal="end" slot="fixed">
    <ion-fab-button color="danger" (click)="addQuote()">
      <ion-icon name="add"></ion-icon>
    </ion-fab-button>
  </ion-fab>
</ion-content>

Here we are iterating on each quote and passing it value to quote-detail component by setting each quote value to quoteData property from quote-detail component.

Conclusion
In this article, we have explored details on how to implement CRUD operation on Ionic firebase using angularFire module. Firebase provides two databases real-time databases and a firestore database. I hope that this article was able to get you up and running with Ionic firebase implementation.

Related posts

1 thought on “Ionic firebase CRUD operation in Details”

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top