New to Kendo UI for AngularStart a free 30-day trial

Performing CRUD Operations with Firebase

Updated on Feb 24, 2026

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

The Kendo UI for Angular Grid can be easily integrated with Firebase, allowing you to perform CRUD operations on a real-time database. The following steps outline the process of setting up the integration and implementing CRUD functionality.

This article uses the AngularFire compatibility API (@angular/fire/compat) which provides a migration path from older AngularFire versions. For new projects, consider using the modular API from @angular/fire/database.

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. Configure Firebase in your Angular project. For standalone components (recommended), add the Firebase configuration to app.config.ts:

    ts
    import { ApplicationConfig } from '@angular/core';
    import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
    import { provideDatabase, getDatabase } from '@angular/fire/database';
    
    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"
    };
    
    export const appConfig: ApplicationConfig = {
        providers: [
            provideFirebaseApp(() => initializeApp(firebaseConfig)),
            provideDatabase(() => getDatabase())
        ]
    };

    Alternatively, for NgModule-based projects, add the Firebase configuration to app.module.ts:

    ts
    import { AngularFireModule } from '@angular/fire/compat';
    import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
    
    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]
    })
    export class AppModule { }
  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.

    ts
    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import { map } from 'rxjs/operators';
    import { AngularFireDatabase, AngularFireList } from '@angular/fire/compat/database';
    import { products } from './products';
    
    @Injectable({ providedIn: 'root' })
    export class EditService {
        private itemsRef: AngularFireList<any>;
    
        constructor(private db: AngularFireDatabase) {
            this.itemsRef = this.db.list('products');
        }
    
        public get(): Observable<any[]> {
            return this.itemsRef.snapshotChanges().pipe(
                map(changes =>
                    changes.map(c => ({
                        key: c.payload.key,
                        ...c.payload.val() as object
                    }))
                )
            );
        }
    
        public save(data: any, isNew?: boolean): void {
            if (isNew) {
                this.itemsRef.push(data);
            } else {
                this.itemsRef.update(data.key, data);
            }
        }
    
        public remove(data: any): void {
            this.itemsRef.remove(data.key);
        }
    
        public resetData(): void {
            this.db.object('/').set(products);
        }
    }
  7. Whenever you want to perform a CRUD operation, call the respective EditService functions.

    ts
    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 }): void {
            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 }): void {
            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 }): void {
            this.closeEditor(sender, rowIndex);
        }
    
        public saveHandler({ sender, rowIndex, formGroup, isNew, dataItem }): void {
            const product = formGroup.value;
            product.key = dataItem.key;
    
            this.editService.save(product, isNew);
    
            sender.closeRow(rowIndex);
        }
    
        public removeHandler({ dataItem }): void {
            this.editService.remove(dataItem);
        }
    
        private closeEditor(grid: any, rowIndex = this.editedRowIndex): void {
            grid.closeRow(rowIndex);
            this.editedRowIndex = undefined;
            this.formGroup = undefined;
        }
    
        public resetData(): void {
            this.editService.resetData();
        }
    }