Edupala

Comprehensive Full Stack Development Tutorial: Learn Ionic, Angular, React, React Native, and Node.js with JavaScript

Ionic firebase CRUD operation in Details

Ionic firebase CRUD example

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 the demo and let’s copy your project API key from the 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. Let’s click on firestore database icon as shown below.

Click on create database will ask us for production or test mode and this is an example. Let’s select test mode, now our database is ready. In later articles, we will learn how to add authentication 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 to our angularFireModule in app.module.ts file. Add the following code in the 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 components, let’s create a quote service to implement our logic.

ionic generate service services/quote

Running the above code will create folder services and add a file called quote.service.ts file. In this file, we are accessing our firebase database which is called collection in the 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 the collections quotes. However, if collections don’t exist then create method will create new collections called quotes and add quote data to them. The delete and update methods need the id of data from collection, in our case quote data have postId as the id by default.

As we defined different methods like creating, updating, or editing, deleting, and retrieving 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 the 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 components. In components, the folder adds a file called shared.module.ts file and 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 exported 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 the 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 the 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’s 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 a quote or not, for edit quotes we get an existing quote from a list of quotes by clicking on the edit button. We have navParams to get quotes from the list for edit quotes, however, for new quotes, we don’t have quotes. For the edit method, we are checking if is add or edit mode, for add mode, we call createQuote method from our quote service and for edit mode, we are calling updateQuote method from the quote service.

List date from Ionic firestore using quote-detail component

In the quote-detail component we display detailed data from each quote, we get quote data from the home component. Let’s edit the quote-details component typescript to get quote data from home using the @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 the quote-detail component, we perform the following task.

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

Edit components/quote-detail/quote.detail.component.html template to display the 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 completed adding, editing, and displaying detailed data from each quote, now we need to get a list of all data from collection quotes. On the home page, we have two main tasks.

  • Add a button to take us to the 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 the home.page.ts file for the 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 the ngOnInit method, we have used getAllQuote from the quote service to get all quotes from the 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 its value to a quote-detail component by setting each quote value to quoteData property from the 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

Ionic firebase CRUD operation in Details

One thought on “Ionic firebase CRUD operation in Details

Leave a Reply

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

Scroll to top