This is a step by step tutorial on how to implement Angular 5 CRUD Operations with Firebase project. So we have to demonstrate Create Read Update and Delete Operations in an Angular 5 project.
Quick Demo of Finished Product :
Following tools and modules are used for this project :
– Angular CLI
– Angular 5
– Firebase project
– Firebase and AngularFire2
– ngx-Toastr
– Bootstrap and Font-Awesome Icons
– VS Code Editor
we assume that you have installed required packages and software for angular 5 development.
Create Angular 5 Application
In-order to create an Angular 5 application, you can use following Angular CLI command
1 | ng new angular5firebasecrud |
it will create an angular 5 application in the current directory and install some default npm packages.
To run this application
1 2 3 4 | //switch to project folder cd angular5firebasecrud //run the project ng serve --open |
it will open this project in your default web browser from 4200 port.
Create Firebase Project
Goto it will automatically log in with your gmail account.
Click On Add Project. it will open a pop-up window, inside that name your project, then click on Add Project button.
After creating firebase project, Project Dashboard / Project Overview will be opened like this.
Click on ‘Add Firebase to your web app’, it will open another popup window with firebase project configuration. copy config object from there.
then past inside environment.ts file as firebaseConfig.
1 2 3 4 5 6 7 8 9 10 11 | export const environment = { production: false, firebaseConfig : { apiKey: "AIzaSyCwVen4n0GUtfFdz08nVj1Ap8jZ-Iy1ikI", authDomain: "dotnet-1197a.firebaseapp.com", databaseURL: "https://dotnet-1197a.firebaseio.com", projectId: "dotnet-1197a", storageBucket: "dotnet-1197a.appspot.com", messagingSenderId: "832930014544" } }; |
Change FirebaseDB Permission
Goto Database > Rules Tab (if not showing click on ‘get started’)
Set following read & write permission
1 2 3 4 5 6 | { "rules": { ".read": true, ".write": true } } |
Install Firebase & Angularfire2 Modules
Firebase and Angularfire2 are the official packages to interact with firebase project from angular applications.
In-order to install these packages use following npm commands
1 | npm install firebase@4.6.1 angularfire2@5.0.0-rc.3 --save |
Open appmodule.ts file, then initialize firebase module with firebase project configuration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //add required import statement import { AngularFireModule } from 'angularfire2'; import { AngularFireDatabaseModule } from 'angularfire2/database'; import { environment } from '../environments/environment'; //initialize firebase module @NgModule({ .... imports: [ ... AngularFireModule.initializeApp(environment.firebaseConfig), AngularFireDatabaseModule ], ... |
Add Required Angular 5 CRUD Components,Model and Service Class
Now we need to add 3 components, to add angular components you can use following Angular-CLI commands
1 2 | //from root component ng g c employees |
remaining two components will be child components for this employees component.
1 2 3 4 5 | //switch to parent component directory cd src\app\employees //create child components ng g c employee ng g c employee-list |
Open appmodule.ts file, Add newly added components into declarations array.
1 2 3 4 5 6 7 8 9 10 11 12 13 | ... import { EmployeesComponent } from './employees/employees.component'; import { EmployeeComponent } from './employees/employee/employee.component'; import { EmployeeListComponent } from './employees/employee-list/employee-list.component'; @NgModule({ .... declarations: [ ... EmployeesComponent, EmployeeComponent, EmployeeListComponent ], ... |
Let’s Start the Design
We’ll use Bootstrap and Font-Awesome Icons For Application Design. So first of all add CDN reference for the style sheets inside index.html .
1 2 3 4 | <!-- Bootstrap --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous"> <!-- font-awesome --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> |
Update app.component.html as follows
1 2 3 | <div class="container"> <app-employees></app-employees> </div> |
Add Following to employees.component.html file.
1 2 3 4 5 6 7 8 9 10 11 | <div class="text-center"> <h2 class="jumbotron">Employee Register</h2> </div> <div class="row"> <div class="col-md-7"> <app-employee></app-employee> </div> <div class="col-md-5"> <app-employee-list></app-employee-list> </div> </div> |
We need Model and Services to design remaining child components.
Create Service and Model Classes
To create these classes let’s add a new folder with name shared inside employees folder (/src/app/ ).
Now create employee model class
1 2 3 4 5 6 | //switch to shared folder cd src\app\employees\shared //create employee model class ng g class employee --type=model //create employee service class ng g s employee |
in this application we deals with employee details like
- Full Name
- Position
- Office Location
- Salary
So we have to add properties corresponding to these employee’s details inside employee.model.ts file.
1 2 3 4 5 6 7 | export class Employee { $key : string; name : string; position : string; office : string; salary : number; } |
$key is used to store unique key automatically generated by firebase DB when we insert a new record.
Inside the service file we will do Firebase CRUD Operation as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import { Injectable } from '@angular/core'; import { AngularFireDatabase, AngularFireList } from 'angularfire2/database' import { Employee} from './employee.model'; @Injectable() export class EmployeeService { employeeList: AngularFireList<any>; selectedEmployee: Employee = new Employee(); constructor(private firebase :AngularFireDatabase ) { } getData(){ this.employeeList = this.firebase.list('employees'); return this.employeeList; } insertEmployee(employee : Employee) { this.employeeList.push({ name: employee.name, position: employee.position, office: employee.office, salary: employee.salary }); } updateEmployee(employee : Employee){ this.employeeList.update(employee.$key, { name: employee.name, position: employee.position, office: employee.office, salary: employee.salary }); } deleteEmployee($key : string){ this.employeeList.remove($key); } } |
EmployeeService contains selectedEmployee property of the type employee model class Employee, to store currently active employee details. employeeList variable store all the employee records from Firebase DB.
In-order to interact with firebase project we have injected AngularFireDatabase as firebase. getData function we initialize employeeList from firebase node ’employees’. we will store employee records under this node. rest of the functions are self explanatory.
Using selectedEmployee property we can design form for insert and update operation inside employee component,
In-order to list inserted employees we can use employeeList property in employee-list component. So first of all we have to Inject this service class these child component. Before that we have to discuss our application structure.
Application Structure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ● src +---● app | +--● employees | | |--employees.component.ts|.html|.css | | +--● employee (employee form) | | | |--employee.component.ts|.html|.css | | | | | +--● employee-list (list inserted employees) | | | |--employee-list.component.ts|.html|.css | | | | | +--● shared | | |--employee.service.ts | | |--employee.model.ts | | | |--app.module.ts (configured firebase connection) | +---● environments | |--environment.ts (saved firebase connection details) | |--index.html (cdn path for bootstrap and font awesome icon) |
We are going to inject EmployeeService inside the Parent Component Employees. and there by we can access the same injected service instance from child components Employee and Employee-List. so whenever we make make changes one child component same change can seen from other child component.
Inject Employee Service in Components :
first of all inject inside parent component Employees
1 2 3 4 5 6 7 8 9 10 | ... import { EmployeeService } from './shared/employee.service' @Component({ ... providers :[EmployeeService] }) export class EmployeesComponent implements OnInit { constructor(private employeeService : EmployeeService) { } ... } |
To inject a class inside a component , mention the class inside component providers array and then create private parameter inside component constructor.
Now we can use this injected instance in child components, for that you can do this ,
Inside employee.component.ts file
1 2 3 4 5 6 7 8 9 10 | ... import { EmployeeService } from '../shared/employee.service'; @Component({ ... }) export class EmployeeComponent implements OnInit { constructor(private employeeService: EmployeeService){ } ... } |
Inside employee-list.component.ts file
1 2 3 4 5 6 7 8 9 10 | ... import { EmployeeService } from '../shared/employee.service'; @Component({ ... }) export class EmployeeListComponent implements OnInit { constructor(private employeeService: EmployeeService){ } ... } |
Angular 5 CRUD Operations Form
we’ll create an employee form to implement Insert and Update Operation with employee Component.So we are going to create Template Driven Form(TDF) using selectedEmployee property from injected EmployeeService Class.
So first of all we have to import FormsModule in appmodule.ts file.
1 2 3 4 5 6 7 8 9 10 | ... import { FormsModule} from '@angular/forms'; ... @NgModule({ ... imports: [ ... FormsModule ], ... |
So you can use following html in employee.component.html file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <form #employeeForm="ngForm" (ngSubmit)="onSubmit(employeeForm)"> <input type="hidden" name="$key" #$key="ngModel" [(ngModel)]="employeeService.selectedEmployee.$key"> <div class="form-group"> <label>Name</label> <input class="form-control" name="name" #name="ngModel" [(ngModel)]="employeeService.selectedEmployee.name" placeholder="Full Name" required> </div> <div class="form-group"> <label>Position</label> <input class="form-control" name="position" #position="ngModel" [(ngModel)]="employeeService.selectedEmployee.position" placeholder="Position"> </div> <div class="form-group"> <label>Office</label> <input class="form-control" name="office" #office="ngModel" [(ngModel)]="employeeService.selectedEmployee.office" placeholder="Office"> </div> <div class="form-group"> <label>Salary</label> <div class="input-group"> <div class="input-group-addon"> <i class="fa fa-dollar"></i> </div> <input class="form-control" name="salary" #salary="ngModel" [(ngModel)]="employeeService.selectedEmployee.salary" placeholder="Salary"> </div> </div> <div class="form-group"> <button class="btn btn-default" type="submit" [disabled]="!employeeForm.valid"> <i class="fa fa-floppy-o"></i> Submit</button> <button class="btn btn-default" type="button" (click)="resetForm(employeeForm)"> <i class="fa fa-repeat"></i> Reset</button> </div> </form> |
and this employee form with data looks like this
This form is a collection of label – text box pair with Submit and Reset button. we have an extra hidden field to store $key of current employee. same form is used for Insert and Update Operation.
Form Validation
required attribute is set to name text box, so employee name is mandatory to submit this form.when name text-box is invalid ng-invalid and ng-dirty class added to it. so based on these we have implement form validation.
when name is empty, employee form as whole is not valid so we add conditional disable attribute to Submit Button.
1 | <button class="btn btn-default" type="submit" [disabled]="!employeeForm.valid"> |
to show validation error indication we’ll show red border around the text box using CSS. so here is the complete css rules for this application
1 2 3 4 5 6 | input.ng-invalid.ng-dirty{ border: 1px solid red; } button:hover,a.btn:hover{ cursor: pointer; } |
Insert,Update and Reset Operation
Inside employee.component.ts file we’ll write code for Insert, Update and Delete Operation.Before that I’m going to install ngx-toastr from npm package. this package helps us to show notification message inside angular applications.
ngx-toastr installation
In-order to install the package you can use following npm command.
1 | npm install ngx-toastr --save |
then add ToastrModule inside appmodule.ts file.
1 2 3 4 5 6 7 8 9 | ... import { ToastrModule } from 'ngx-toastr'; @NgModule({ ... imports: [ ... ToastrModule.forRoot() ], ... |
Now you can add following code inside employee component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import { Component, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms' import { EmployeeService } from '../shared/employee.service'; import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-employee', templateUrl: './employee.component.html', styleUrls: ['./employee.component.css'] }) export class EmployeeComponent implements OnInit { constructor(private employeeService: EmployeeService, private tostr: ToastrService) { } ngOnInit() { this.resetForm(); } onSubmit(employeeForm: NgForm) { if (employeeForm.value.$key == null) this.employeeService.insertEmployee(employeeForm.value); else this.employeeService.updateEmployee(employeeForm.value); this.resetForm(employeeForm); this.tostr.success('Submitted Succcessfully', 'Employee Register'); } resetForm(employeeForm?: NgForm) { if (employeeForm != null) employeeForm.reset(); this.employeeService.selectedEmployee = { $key: null, name: '', position: '', office: '', salary: 0, } } } |
restForm function is used reset form controls value to initial stage, we called this function from reset button click event and from ngOnint Lifecycle Hook to initialise the form.
Inside the form submit event function OnSubmit, we implement both insert and update operation based on $key value. to show the success message we use ToastrService class object tostr.
List Inserted Records and Delete Operation
Using employee-list component we’ll list all inserted employees and Delete Operation.
you can add following inside employee-list component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import { Component, OnInit } from '@angular/core'; import { EmployeeService } from '../shared/employee.service'; import { Employee } from '../shared/employee.model'; import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-employee-list', templateUrl: './employee-list.component.html', styleUrls: ['./employee-list.component.css'] }) export class EmployeeListComponent implements OnInit { employeeList: Employee[]; constructor(private employeeService: EmployeeService, private tostr: ToastrService) { } ngOnInit() { var x = this.employeeService.getData(); x.snapshotChanges().subscribe(item => { this.employeeList = []; item.forEach(element => { var y = element.payload.toJSON(); y["$key"] = element.key; this.employeeList.push(y as Employee); }); }); } onEdit(emp: Employee) { this.employeeService.selectedEmployee = Object.assign({}, emp); } onDelete(key: string) { if (confirm('Are you sure to delete this record ?') == true) { this.employeeService.deleteEmployee(key); this.tostr.warning("Deleted Successfully", "Employee register"); } } } |
Inside this we have injected EmployeeService and ToastrService Class. Created an Employee array employeeList. Inside the ngOnint Lifecycle Hook, we subscribe to firebase db collection and we store employee records inside the array.Using this array variable we will display inserted employee inside employee-list component.
employee-list.component.html looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <h6 class="text-center">Employee Register</h6><br/> <table class="table table-sm table-hover"> <tr *ngFor="let employee of employeeList"> <td>{{employee.name}}</td> <td>{{employee.position}}</td> <td> <a class="btn" (click)="onEdit(employee)"> <i class="fa fa-pencil-square-o"></i> </a> <a class="btn" (click)="onDelete(employee.$key)"> <i class="fa fa-trash-o"></i> </a> </td> </tr> </table> |
Component design will look like this
when we click on pencil () button it will onEdit function to populate corresponding record inside the employee form, after changing user update operation as we discussed before.(inside employee component).
Using trash icon we implemented delete operation with onDelete function.
Download Project Source Code : https://goo.gl/83tyjH
Step by Step Video Tutorial
Thanks for the visit, hope you liked it, let me know your comments.
Leave a Reply
1 Comment on "Angular 5 CRUD Operations With Firebase"
I just followed this tutorial. Everything worked perfectly! Thanks!!!