Cell Editing in Angular Data Grid
5 Sep 202618 minutes to read
Cell editing provides a streamlined way to update individual cell values directly within the grid. It is designed for quick, inline modifications, making data entry and corrections more efficient. This approach ensures that changes are applied seamlessly to large datasets while maintaining consistency with the grid’s overall editing experience.
Enable cell editing
To enable cell editing in the Data Grid, configure the editSettings->mode property to Cell and set the editSettings->allowEditing property to true. This configuration allows individual cell values to be updated directly within the grid.
import { billingData } from './datasource';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DatePickerAllModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars';
import { AutoCompleteModule, MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns';
import { GridComponent, EditService, SaveEventArgs, EditEventArgs, EditSettingsModel, FilterSettingsModel, GridModule, PageService, SortService, ToolbarItems, ToolbarService, FilterService } from '@syncfusion/ej2-angular-grids';
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs';
@Component({
imports: [
GridModule,
DatePickerAllModule,
FormsModule,
TimePickerModule,
FormsModule,
TextBoxModule,
MultiSelectModule,
AutoCompleteModule
],
providers: [EditService, ToolbarService, SortService, PageService, FilterService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid [dataSource]='data' [editSettings]='editSettings' [allowPaging]='true' [allowSorting]='true' [allowFiltering]='true' [filterSettings]='filterSettings'
[toolbar]='toolbar' (actionBegin)="actionBegin($event)" (actionComplete)="actionComplete($event)">
<e-columns>
<e-column field="BillID" headerText="Bill ID" width="120" isPrimaryKey="true" [validationRules]="{ required: true }"></e-column>
<e-column field="BillDate" headerText="Bill Date" width="140" format="yMd" editType="datepickeredit"></e-column>
<e-column field="Customer" headerText="Customer Name" width="150" [validationRules]="{ required: true }"></e-column>
<e-column field="Product" headerText="Product Name" width="150" editType="dropdownedit"></e-column>
<e-column field="Category" headerText="Category" width="130" editType="dropdownedit"></e-column>
<e-column field="Quantity" headerText="Quantity" width="100" textAlign="Right" format="N0"></e-column>
<e-column field="Price" headerText="Price" width="100" textAlign="Right" editType="numericedit" format="C2"></e-column>
<e-column field="Total" headerText="Total" width="120" textAlign="Right" format="C2"></e-column>
<e-column field="PaymentStatus" headerText="Payment Status" width="130" editType="dropdownedit"></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
public filterSettings?: FilterSettingsModel;
@ViewChild('grid')
public grid?: GridComponent;
ngOnInit(): void {
this.data = billingData;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Cell' };
this.toolbar = ['Add', 'Delete', 'Update', 'Cancel'];
this.filterSettings = { type: 'CheckBox' };
}
actionComplete(args: SaveEventArgs) {
if (args.action === 'edit' && args.requestType === 'save' && (args.columnName === 'Quantity' || args.columnName === 'Price')) {
var total = args.data.Quantity * args.data.Price;
this.grid.updateCell(args.index, "Total", total);
}
}
actionBegin(args: EditEventArgs) {
if (args.requestType === 'beginEdit' && args.columnName === 'Total') {
args.cancel = true;
}
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));When editing is enabled, it is necessary to set the isPrimaryKey property value to
truefor the unique column to ensure accurate data updates.
Single-click editing
Single-click editing allows a cell to enter edit mode with a single click instead of the default interaction. This seamless experience is achieved by using the editCell method for rapid, efficient data modification.
To implement this, bind the click event for the grid and, within the event handler, call the editCell method based on the clicked target element. This ensures that the editing mode is triggered when clicking on a specific element within the grid.
import { productDatas } from './datasource';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DatePickerAllModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars';
import { AutoCompleteModule, MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns';
import { EditService, EditSettingsModel, GridComponent, GridModule, PageService, SortService, ToolbarItems, ToolbarService } from '@syncfusion/ej2-angular-grids';
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs';
@Component({
imports: [
GridModule,
DatePickerAllModule,
FormsModule,
TimePickerModule,
FormsModule,
TextBoxModule,
MultiSelectModule,
AutoCompleteModule
],
providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid id="grid" [dataSource]='data' [allowPaging]="true" [editSettings]='editSettings' [toolbar]='toolbar' (created)="created()">
<e-columns>
<e-column field="ProductID" headerText="Product ID" width="120" textAlign="Right" isPrimaryKey="true" [validationRules]="{ required: true }"></e-column>
<e-column field="ProductCategory" headerText="Product Category" width="140" [validationRules]="{ required: true }"></e-column>
<e-column field="ShippingMethod" headerText="Shipping Method" width="140" editType="dropdownedit"></e-column>
<e-column field="StockQuantity" headerText="StockQuantity" width="150" editType="numericedit" format="N0"></e-column>
<e-column field="Discount" headerText="Discount (%)" width="170" editType="numericedit" format="C2"></e-column>
<e-column field="Revenue" headerText="Revenue" width="170" editType="numericedit" format="C2"></e-column>
<e-column field="TransactionDate" headerText="TransactionDate" width="170" editType="datetimepickeredit" format="yMd"></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
@ViewChild('grid')
public grid?: GridComponent;
ngOnInit(): void {
this.data = productDatas;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Cell' },
this.toolbar = ['Add', 'Delete', 'Update', 'Cancel'];
}
created = () => {
(this.grid as GridComponent).getContentTable().addEventListener('click', (args) => {
if ((args.target as HTMLElement).classList.contains('e-rowcell')) {
(this.grid as GridComponent).editModule.editCell(args.target.closest('tr').rowIndex,
(this.grid as GridComponent).getColumnByIndex(parseInt((args.target as HTMLElement).getAttribute('aria-colindex') as string) - 1).field);
}
});
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Cancel edit based on condition
The Data Grid can prevent edit operations for specific cells based on custom conditions. This functionality is achieved by leveraging the actionBegin event of the grid component. This event is triggered when a CRUD (Create, Read, Update, Delete) operation is initiated in the grid.
This customization is useful when restricting editing for certain cells, such as read-only data, calculated values, or protected information. It helps maintain data integrity and ensures that only authorized changes can be made in the grid.
To cancel the edit operation based on a specific condition, handle the actionBegin event of the grid component and check the requestType parameter. This parameter indicates the type of action being performed:
| Request Type | Description |
|---|---|
beginEdit |
Editing an existing record |
add |
Creating a new record |
save |
Updating a new or existing record |
delete |
Deleting an existing record |
Apply the desired condition and cancel the operation by setting the args.cancel property to true.
import { data } from './datasource';
import { Component, OnInit } from '@angular/core';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { EditEventArgs, EditService, EditSettingsModel, GridModule, ToolbarItems, ToolbarService } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [ GridModule,ButtonModule],
providers: [EditService, ToolbarService],
standalone: true,
selector: 'app-root',
template: `<button ejs-button id="small" (click)="btnClick($event)">Grid is Addable
</button>
<div class="control-section" style="padding-top:20px">
<ejs-grid [dataSource]='data' [editSettings]='editSettings'
[toolbar]='toolbar' (actionBegin)="actionBegin($event)" height='240px'>
<e-columns>
<e-column field='EmployeeID' headerText='Employee ID' textAlign= 'Right' isPrimaryKey='true' [validationRules]='orderIDRules' width=100></e-column>
<e-column field='EmployeeName' headerText='Employee Name' [validationRules]='customerNameRules' width=120 format= 'C2'></e-column>
<e-column field='Role' headerText='Role' [validationRules]='roleIDRules' width=120></e-column>
<e-column field='EmployeeCountry' headerText='Employee Country' editType= 'dropdownedit' width=150></e-column>
</e-columns>
</ejs-grid>
</div>`
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
public isAddable: boolean = true;
public orderIDRules?: object;
public roleIDRules?: object;
public customerNameRules?: object;
ngOnInit(): void {
this.data = data;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Cell' };
this.toolbar = ['Add', 'Delete', 'Update', 'Cancel'];
this.orderIDRules = { required: true };
this.roleIDRules = { required: true, minLength: 5 };
this.customerNameRules = { required: true }
}
actionBegin(args: EditEventArgs) {
if (args.requestType == 'beginEdit' && args.rowData as { Role?: string }['Role'] == 'Admin') {
args.cancel = true;
}
else if (args.requestType == 'delete' && (args as any).data[0].Role == 'Admin') {
args.cancel = true;
}
else if (args.requestType == 'add') {
if (!this.isAddable) {
args.cancel = true;
}
}
}
btnClick(args: MouseEvent) {
(args.target as HTMLElement).innerText == 'GRID IS ADDABLE' ? ((args.target as HTMLElement).innerText = 'Grid is Not Addable') : ((args.target as HTMLElement).innerText = 'Grid is Addable');
this.isAddable = !this.isAddable;
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));