New to Kendo UI for Angular? Start a free 30-day trial

Performing CRUD Operations with Firebase

Environment

ProductProgress® Kendo UI for Angular Grid

Description

How can I use Google's FireBase as a data source for the Grid and perform CRUD operations?

Solution

This sample application is a client-side Angular project which demonstrates how to perform CRUD operations in the Kendo UI for Angular Grid that uses Google's real-time Firebase database for its backend.

Configuring the Firebase Database

  1. Create a clean Angular project by using the Angular CLI tool.

  2. Create a new Firebase project by using the Google instructions.

  3. Install the @angular/fire NPM package by running npm install @angular/fire firebase --save.

  4. In the app.module.ts file, add the Firebase configuration to the Angular project.

        const firebaseConfig = {
            apiKey: "AIzaSyD68ysdlWJT8yLB7kSUcCuxlrWBqUPX4Tg",
            authDomain: "kendo-grid-crud.firebaseapp.com",
            databaseURL: "https://kendo-grid-crud.firebaseio.com",
            projectId: "kendo-grid-crud",
            storageBucket: "kendo-grid-crud.appspot.com",
            messagingSenderId: "1005892024994",
            appId: "1:1005892024994:web:e74d331eb7cd46f13335fb"
        };
    
        @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            BrowserModule,
            AngularFireModule.initializeApp(firebaseConfig),
            AngularFireDatabaseModule,
            GridModule,
            BrowserAnimationsModule,
            ButtonsModule
        ],
        providers: [EditService],
        bootstrap: [AppComponent]
  5. Add the Grid package to the project and follow the example on Reactive Forms editing.

  6. Create a service that holds the functions for the CRUD operations.

        import { Injectable } from '@angular/core';
        import { Observable } from 'rxjs';
        import { AngularFireDatabase } from '@angular/fire/database';
        import { products } from './products';
    
        @Injectable()
        export class EditService{
            constructor(public db: AngularFireDatabase) {}
    
            public get(): Observable<any>{
                return this.db.list('products').valueChanges();
            }
    
            public save(data: any, isNew?: boolean) {
                if(isNew){
                    let newPostKey = this.db.database.ref().child('products').push().key;
                    data.key = newPostKey;
                    this.db.database.ref('products/' + newPostKey).set(data);
                }else{
                    this.db.database.ref('products/' + data.key).set(data);
                }        
            }
    
            public remove(data: any) {
                this.db.database.ref('products/' + data.key).remove();
            }
    
            public resetData(){
                this.db.database.ref('/').set(products);
            }
        }
  7. Whenever you want to perform a CRUD operation, call the respective EditService functions.

        import { Component } from '@angular/core';
        import { Observable } from 'rxjs';
    
        import { FormGroup, FormControl, Validators } from '@angular/forms';
    
        import { EditService } from './edit.service';
    
        @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.css']
        })
        export class AppComponent {
            public formGroup: FormGroup;
            private editedRowIndex: number;
            public view: Observable<any>;
    
            constructor(public editService: EditService) {
                this.view = this.editService.get();
            }
    
            public addHandler({sender}) {
                this.closeEditor(sender);
    
                this.formGroup = new FormGroup({
                    'ProductID': new FormControl(),
                    'ProductName': new FormControl('', Validators.required),
                    'UnitPrice': new FormControl(0),
                    'UnitsInStock': new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
                    'Discontinued': new FormControl(false)
                });
    
                sender.addRow(this.formGroup);
            }
    
            public editHandler({sender, rowIndex, dataItem}) {
                this.closeEditor(sender);
    
                this.formGroup = new FormGroup({
                    'ProductID': new FormControl(dataItem.ProductID),
                    'ProductName': new FormControl(dataItem.ProductName, Validators.required),
                    'UnitPrice': new FormControl(dataItem.UnitPrice),
                    'UnitsInStock': new FormControl(
                            dataItem.UnitsInStock,
                            Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
                    'Discontinued': new FormControl(dataItem.Discontinued)
                });
    
                this.editedRowIndex = rowIndex;
    
                sender.editRow(rowIndex, this.formGroup);
            }
    
            public cancelHandler({sender, rowIndex}) {
                this.closeEditor(sender, rowIndex);
            }
    
            public saveHandler({sender, rowIndex, formGroup, isNew, dataItem}) {
                const product = formGroup.value;
                product.key = dataItem.key;
    
                this.editService.save(product, isNew);
    
                sender.closeRow(rowIndex);
            }
    
            public removeHandler({dataItem}) {
                this.editService.remove(dataItem);
            }
    
            private closeEditor(grid, rowIndex = this.editedRowIndex) {
                grid.closeRow(rowIndex);
                this.editedRowIndex = undefined;
                this.formGroup = undefined;
            }
    
            public resetData(){
                this.editService.resetData();
            }
        }