Angular 12 Firestore Realtime CRUD App Example Tutorial

Throughout this Angular 12 Firebase CRUD example, you will learn how to create CRUD (Create, Read, Update, Delete) operations in Angular application, not just that you will also learn how to handle CRUD operation data in the Firebase database in realtime.

Firebase is a NoSQL database created by Google; It is mainly used for propelling forward richer and faster web & mobile application development. Needless to say, but it provides two subtle cloud-based and client-accessible database solutions, which is best used for real-time data syncing.

In this step by step angular firebase realtime database crud tutorial, we will use Firestore, and you will use firestore in angular for building angular firestore crud example.

Angular 12 Firestore Realtime CRUD Operations Example

  • Install Angular Application
  • Setting Up Bootstrap Package
  • Setting Up Firestore Database in Angular
  • Create CRUD Methods using Angular Service
  • Create a User Model
  • Create Routes and Navigation
  • Create Forms with Reactive Forms
  • Implement CRUD Operations in Angular with Firestore
  • Start Angular Development Server

Prerequisites

This tutorial wants you to have the following tools installed on your machine:

  • Latest version of Angular CLI
  • Latest version of Node js and NPM
  • Code editor

Install Angular Application

Open the terminal, execute the command to install the latest version of the Angular app.

ng new angular-firestore-crud

Once the app manifested on your system, make sure you enter into the project root.

cd angular-firebase-realtime-crud

Further, you need to generate components:

ng g c create-user

ng g c list-user

ng g c edit-user

Setting Up Bootstrap Package

Bootstrap library allows you to create seamless user interface components in angular, so install this profound package:

npm install bootstrap

Open and update the Bootstrap CSS path within styles array inside the angular.json:

...
...
"styles": [
     "node_modules/bootstrap/dist/css/bootstrap.min.css",
     "src/styles.scss"
]

Setting Up Firestore Database in Angular

First, you need a Firebase project, and It will allow you to handle the CRUD data recklessly. For setting up the database, you need to visit the Firebase Console.

Inside the Firebase project dashboard, go to Project overview > Develop > Database, and without wasting much time, create a new Firestore database.

For the testing purpose, enable only test mode; it will relinquish the permission issue to interact with the database.

Moreover, you have to copy the Firebase configuration that you need to establish the communication between Angular and Firebase.

Next, you have to install the @angular/fire package in angular:

npm install firebase @angular/fire

Declare the firebase configuration that you generated after creating the Firebase project, so open enviorment.ts file next update the Firebase modules:

// environment.ts

export const environment = {
  production: false,
  firebaseConfig: {
    apiKey: "xxxxxx-xxxxxx_xxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxx_xxxxxxxxxxxxxxxxxx",
    databaseURL: "xxxxxx_xxxxxxxxxxxxxxxxxx",
    projectId: "xxxxxx_xxxxxxxxxxxxxxxxxx",
    storageBucket: "xxxxxx_xxxxxxxxxxxxxxxxxx",
    messagingSenderId: "xxxxxxxxxxxxxxxxxx",
    appId: "1:xxxxxxxxxxxxxxxxxx:web:xxxxxxxxxxxxxxxxxx"
  }
};

Update the Firebase modules in the app.module.ts file, as shown below:

...
...

import { environment } from "../environments/environment";
import { AngularFireModule } from "@angular/fire";
import { AngularFirestoreModule } from "@angular/fire/firestore";

@NgModule({
  ...
  imports: [
    AngularFireModule.initializeApp(environment.firebaseConfig),
    AngularFirestoreModule
  ],
  ...
  ...
})

export class AppModule { }

Import AngularFireModule, AngularFirestoreModule database modules also environment variables. Additionally, define these modules in the imports array, call the initializeApp() method and pass the environment.firebaseConfig to make the accord between angular and firebase.

Create a User Model

Next, create a User model class; in general, a model class holds the data object’s values. On top of that, it defines the structure of the data, and it stands first in the MVC software design pattern.

ng g class user --type=model

Further, open and update the src/user.model.ts file:

export class User {
    id: string;
    name: string;
    email: string;
    contact: string;
}

Create CRUD Methods with Angular Service

You have to create an angular service file to define the CRUD methods to manage the user data. Angular service is the best way to create and keep the reusable code in one place.

ng g service user

Open and update the CRUD methods in recently manifested angular service file from above command in user.service.ts:

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { User } from '../app/user.model';

@Injectable({
  providedIn: 'root'
})

export class UserService {

  constructor(private angularFirestore: AngularFirestore) {}

  getUserDoc(id) {
    return this.angularFirestore
    .collection('user-collection')
    .doc(id)
    .valueChanges()
  }

  getUserList() { 
    return this.angularFirestore
    .collection("user-collection")
    .snapshotChanges();
  }

  createUser(user: User) {
    return new Promise<any>((resolve, reject) =>{
      this.angularFirestore
        .collection("user-collection")
        .add(user)
        .then(response => { console.log(response) }, error => reject(error));
    });
  }

  deleteUser(user) {
    return this.angularFirestore
      .collection("user-collection")
      .doc(user.id)
      .delete();
  }
  
  updateUser(user: User, id) {
    return this.angularFirestore
      .collection("user-collection")
      .doc(id)
      .update({
        name: user.name,
        email: user.email,
        contact: user.contact
      });
  }
}

Create Routes and Navigation

Whether you want to navigate within the app or make HTTP calls, you need to add routes in the app-routing.modules.ts file:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';

import { CreateUserComponent } from './create-user/create-user.component';
import { ListUserComponent } from './list-user/list-user.component';
import { EditUserComponent } from './edit-user/edit-user.component';

const routes: Routes = [
  { path: '', redirectTo: '/create', pathMatch: 'full' },
  { path: 'create', component: CreateUserComponent },
  { path: 'list-users', component: ListUserComponent },
  { path: 'update-user/:id', component: EditUserComponent }
];

@NgModule({
  imports: [CommonModule,RouterModule.forRoot(routes)],
  exports: [RouterModule],
  declarations: []
})

export class AppRoutingModule { }

The router-outlet directive displays the registered routes in the view in addition to its component, so open and update the app.component.html file:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">RemoteStack</a>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link" routerLink="/create" routerLinkActive="active">Create</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" routerLink="/list-users" routerLinkActive="active">Show Users</a>
        </li>
      </ul>
    </div>
  </div>
</nav>

<div class="container mt-5">
  <router-outlet></router-outlet>
</div>

Import Form Modules

To handle form data you have to import ReactiveFormsModule and FormsModule. So, open and update app.module.ts file:

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

@NgModule({
  imports: [
    FormsModule,
    ReactiveFormsModule
  ],
})

export class AppModule { }

Create

To add or create a document in the Firestore real-time database, you need to create the form, invoke the for with formGroup directive, bind with ngSubmit. Also, declare the form-control with associated form values.

Open and update create-user.component.html file:

<form [formGroup]="userForm" (ngSubmit)="onSubmit()" novalidate>
  <div class="mb-3">
    <label>Name</label>
    <input type="text" formControlName="name" class="form-control" required>
  </div>

  <div class="mb-3">
    <label>Email</label>
    <input type="email" formControlName="email" class="form-control" required>
  </div>

  <div class="mb-3">
    <label>Contact</label>
    <input type="text" formControlName="contact" class="form-control" required>
  </div>

  <div class="mb-3">
    <button type="submit" class="btn btn-primary" [disabled]="!userForm.valid">Create</button>
  </div>
</form>

Import service, form, and router modules, inject the modules in the constructor. Evoke a form with reactive form equally important makes the request using the createUser method.

Open and update create-user.component.ts file:

import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from "@angular/router";


@Component({
  selector: 'app-create-user',
  templateUrl: './create-user.component.html',
  styleUrls: ['./create-user.component.scss']
})

export class CreateUserComponent implements OnInit {
  public userForm: FormGroup;

  constructor(
    public userService: UserService,
    public formBuilder: FormBuilder,
    public router: Router
  ) { 
    this.userForm = this.formBuilder.group({
      name: [''],
      email: [''],
      contact: ['']
    })      
  }

  ngOnInit(): void {
  }

  onSubmit() {
    this.userService.createUser(this.userForm.value);
    this.router.navigate(['list-users']); 
   };
}

Read and Delete

Create a table with Bootstrap UI component to display the data and define two actions for deleting document and accessing the edit document template.

Open and update list-user.component.html:

<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Name</th>
      <th scope="col">Email</th>
      <th scope="col">Contact</th>
      <th scope="col">Action </th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let user of Users; let i = index">
      <th scope="row">{{ i + 1 }}</th>
      <td>{{ user.name }}</td>
      <td>{{ user.email }}</td>
      <td>{{ user.contact }}</td>
      <td>
        <span (click)="removeUser(user)" class="text-danger">Delete</span> &nbsp;
        <span routerLink="/update-user/{{user.id}}" class="text-primary">Edit</span>
      </td>
    </tr>
  </tbody>
</table>

Open and update list-user.component.ts:

import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';
import { User } from '../user.model';

@Component({
  selector: 'app-list-user',
  templateUrl: './list-user.component.html',
  styleUrls: ['./list-user.component.scss']
})

export class ListUserComponent implements OnInit {
  Users: User[];

  constructor(private userService: UserService) { }

  ngOnInit() {
    this.userService.getUserList().subscribe(res => {
      this.Users = res.map( e => {
        return {
          id: e.payload.doc.id,
          ...e.payload.doc.data()
        } as User;
      })
    });    
  }

  removeUser = user => this.userService.deleteUser(user);
}

Firebase Update Document

To update the firebase or firestore document, create the form, access the method to make the firestore document update request.

Open and update edit-user.component.html:

<form [formGroup]="editForm" (ngSubmit)="onSubmit()" novalidate>
  <div class="mb-3">
    <label>Name</label>
    <input type="text" formControlName="name" class="form-control" required>
  </div>

  <div class="mb-3">
    <label>Email</label>
    <input type="email" formControlName="email" class="form-control" required>
  </div>

  <div class="mb-3">
    <label>Contact</label>
    <input type="text" formControlName="contact" class="form-control" required>
  </div>

  <div class="mb-3">
    <button type="submit" class="btn btn-primary">Update</button>
  </div>
</form>

Open and update edit-user.component.ts:

import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';
import { Router, ActivatedRoute } from "@angular/router";
import { FormBuilder, FormGroup } from '@angular/forms';


@Component({
  selector: 'app-edit-user',
  templateUrl: './edit-user.component.html',
  styleUrls: ['./edit-user.component.scss']
})

export class EditUserComponent implements OnInit {
  
  public editForm: FormGroup;
  userRef: any

  constructor(
    public userService: UserService,
    public formBuilder: FormBuilder,
    private act: ActivatedRoute,
    private router: Router
  ) {
    this.editForm = this.formBuilder.group({
      name: [''],
      email: [''],
      contact: ['']
    })
  }

  ngOnInit(): void {
    const id = this.act.snapshot.paramMap.get('id');

    this.userService.getUserDoc(id).subscribe(res => {
      this.userRef = res;
      this.editForm = this.formBuilder.group({
        name: [this.userRef.name],
        email: [this.userRef.email],
        contact: [this.userRef.contact]
      })      
    })
  }

  onSubmit() {
    const id = this.act.snapshot.paramMap.get('id');
    
    this.userService.updateUser(this.editForm.value, id);
    this.router.navigate(['list-users']);
  };

}

Run Angular Firebase CRUD Project

To see the Angular Firestore CRUD application in action, you need to start the development server:

ng serve --open

Angular Firestore CRUD Example

Conclusion

Firebase is a top-notch database that is preferred for building web and mobile application for real-time updates; Firebase saves your tons of precious time that you may lose in developing the robust backend.

It doesn’t cost exorbitantly high, especially if you are a novice developer, then you can try your hands on its free test projects. Developing an enterprise-level application is comfortable with Firebase, and i am sure you will like its immaculate documentation for development.

This tutorial only highlighted some essential points; nonetheless, this angular firebase crud example will help you propel forward in your full-stack development journey, i hope you must have liked this tutorial.

Download the complete source code from GitHub.