Angular Data Grid Custom Editing Service
The Angular Grid provides built-in editing directives that handle data operations automatically. However, for complex scenarios where you need more control over the CRUD operations, data validation, or integration with external APIs, you can implement a custom editing service.
Each editing directive exposes an editService
property that allows you to replace the default data handling with your own custom logic. The custom service manages the create, read, update, and delete operations and must implement the EditService
interface.
If the Grid is not bound to a plain array, you must specify an
EditService
.
The following example demonstrates how to implement a custom editing service that batches multiple changes and allows the user to submit them simultaneously with manual save/cancel functionality.
Setup
To implement a custom editing service for the Grid:
-
Create a service that implements the
EditService
interface and extendsBehaviorSubject
to manage editing operations and track data changes.typescript@Injectable() export class MyEditService extends BehaviorSubject<Product[]> implements EditService { private data: Product[] = []; private originalData: Product[] = []; private createdItems: Product[] = []; private updatedItems: Product[] = []; private deletedItems: Product[] = []; constructor(private http: HttpClient) { super([]); } }
The service extends
BehaviorSubject
to provide reactive data updates that automatically notify the Grid when data changes. The separate arrays track different types of changes, enabling further batch processing where all changes can be submitted together. -
Implement the required CRUD methods of the
EditService
interface. The Grid will call these methods when users perform the corresponding editing operations.tspublic create(item: Product): void { // Track new items for batch processing and add them to the data in the UI. this.createdItems.push(item); this.data.unshift(item); // Notify Grid of data change. super.next(this.data); }
-
Implement the remaining method required by the
EditService
interface, and add custom helper methods for managing the editing state.typescript// Required by EditService interface. public assignValues(target: unknown, source: unknown): void { Object.assign(target, source); } // Custom helper methods for the implementation. public isNew(item: Product): boolean { return !item.ProductID; } public hasChanges(): boolean { return Boolean(this.deletedItems.length || this.updatedItems.length || this.createdItems.length); }
The
assignValues
method is used by the Grid to update item values during editing operations. -
Create a method that handles submitting all pending changes to the server, and another method for discarding all changes and reverting to the original state.
tspublic saveChanges(): void { if (!this.hasChanges()) { return; } const completed = []; if (this.deletedItems.length) { completed.push(this.fetch(REMOVE_ACTION, this.deletedItems)); } if (this.updatedItems.length) { completed.push(this.fetch(UPDATE_ACTION, this.updatedItems)); } if (this.createdItems.length) { completed.push(this.fetch(CREATE_ACTION, this.createdItems)); } // Clear tracking arrays. this.reset(); // Wait for all operations to complete, then refresh data. zip(...completed).subscribe(() => this.read()); }
The
saveChanges
method groups all pending changes by type and submits them as coordinated server requests using RxJSzip
to wait for all operations to complete. This approach provides better error handling and transaction-like behavior. -
Configure the Grid to use your custom service by setting the
editService
property of the Grid and providing the service in your component.typescript@Component({ providers: [MyEditService], template: ` <kendo-grid [kendoGridInCellEditing]="createFormGroup" [editService]="editService" ... > </kendo-grid> ` }) export class AppComponent { constructor(public editService: MyEditService) {} }
-
Include custom action buttons in the Grid's toolbar, which will allow users to manually control when changes are collectively submitted or discarded, providing full control over the batch operations.
HTML<ng-template kendoGridToolbarTemplate> <button kendoGridAddCommand>Add new</button> <button kendoButton [disabled]="!editService.hasChanges()" (click)="saveChanges(grid)"> Save Changes </button> <button kendoButton [disabled]="!editService.hasChanges()" (click)="cancelChanges(grid)"> Cancel Changes </button> </ng-template>