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

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.

Change Theme
Theme
Loading ...

Setup

To implement a custom editing service for the Grid:

  1. Create a service that implements the EditService interface and extends BehaviorSubject 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.

  2. Implement the required CRUD methods of the EditService interface. The Grid will call these methods when users perform the corresponding editing operations.

    ts
    public 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);
    }
  3. 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.

  4. 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.

    ts
    public 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 RxJS zip to wait for all operations to complete. This approach provides better error handling and transaction-like behavior.

  5. 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) {}
    }
  6. 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>
In this article
SetupSuggested Links
Not finding the help you need?
Contact Support