Inline editing in Angular Grid component

17 Sep 202524 minutes to read

The Angular Grid component provides an efficient inline editing feature, enabling direct modification of row or cell values within the grid. Inline editing is ideal for streamlining data entry and updates without invoking a separate form. In normal edit mode, the selected record enters an editable state, allowing updates to cell values which are then saved back to the data source.

Enable inline editing by setting the editSettings.mode property to Normal. This property determines the editing mode of the Grid.

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { EditSettingsModel,ToolbarItems } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid [dataSource]='data' [editSettings]='editSettings' 
               [toolbar]='toolbar' height='273px'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    isPrimaryKey='true' [validationRules]='orderIDRules' width=100>
                    </e-column>
                    <e-column field='CustomerID' headerText='Customer ID' 
                    [validationRules]='customerIDRules' width=120></e-column>
                    <e-column field='Freight' headerText='Freight' textAlign= 'Right'
                    editType= 'numericedit' [validationRules]='freightIDRules' 
                    width=120 format= 'C2'></e-column>
                    <e-column field='ShipCountry' headerText='Ship Country' 
                    editType= 'dropdownedit' width=150></e-column>
                </e-columns>
              </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: ToolbarItems[];
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightIDRules?: object;

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
        this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
        this.orderIDRules = { required: true };
        this.customerIDRules = { required: true, minLength: 5 };
        this.freightIDRules={required: true, min: 1, max:1000 }

    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

  • Normal edit mode is the default editing mode.
  • When editing is enabled, ensure the isPrimaryKey property is set to true on the unique column.

Automatically update a specific column based on changes in another column

Automatically updating column values based on edits in related columns enhances workflow efficiency. Use the Cell Edit Template feature to perform real-time calculations or synchronize values. Set the editType and customize the edit property to define editing behavior.

Example: The TotalCost column value is updated dynamically in response to changes in UnitPrice and UnitInStock columns.

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit, ViewChild } from '@angular/core';
import { productData } from './datasource';
import { EditSettingsModel, ToolbarItems, GridComponent } from '@syncfusion/ej2-angular-grids';
import { ChangeEventArgs } from '@syncfusion/ej2-buttons';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
  selector: 'app-root',
  template: `
        <ejs-grid #grid  [dataSource]="data" [editSettings]="editSettings" 
        [toolbar]="toolbar" height="273px">
          <e-columns>
            <e-column field="ProductID" headerText="Product ID" textAlign="Right" 
            isPrimaryKey="true" [validationRules]='orderIDRules' width="100"></e-column>
            <e-column field="ProductName" headerText="Product Name" width="120" 
            [validationRules]=' productNameRules'></e-column>
            <e-column field="UnitPrice" headerText="Unit Price" editType="numericedit" 
            [edit]="priceParams" width="150" [validationRules]='unitIDRules' format="C2" 
            textAlign="Right"></e-column>
            <e-column field="UnitsInStock" headerText="Units In Stock" editType="numericedit" 
            [edit]="stockParams" [validationRules]='stockIDRules'  width="150" 
            textAlign="Right"></e-column>
            <e-column field="TotalCost" headerText="Total Cost" width="150" 
            [allowEditing]='false' format="C2" textAlign="Right"></e-column>
          </e-columns>
        </ejs-grid>`
})
export class AppComponent implements OnInit {

  @ViewChild('grid')
  public grid?: GridComponent;
  public data?: Object[];
  public editSettings?: EditSettingsModel;
  public toolbar?: ToolbarItems[];
  public priceParams?: Object;
  public stockParams?: Object;
  public orderIDRules?: object;
  public unitIDRules?: object;
  public stockIDRules?: object;
  public productNameRules?: object;

   
  ngOnInit(): void {
    this.data = productData;
    this.editSettings = {
      allowEditing: true,
      allowAdding: true,
      allowDeleting: true
    };
    this.orderIDRules = { required: true };
    this. productNameRules = { required: true };
    this.unitIDRules={ required: true, min: 1 }
    this.unitIDRules={ required: true, min: 1 }
    this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    this.priceParams = { params: { change: this.calculateTotalCost.bind(this) } };
    this.stockParams = { params: { change: this.calculateTotalCost.bind(this) } };
  }
  calculateTotalCost(args:ChangeEventArgs): void {
    const formEle = ((this.grid as GridComponent).element.querySelector('form') as HTMLFormElement)['ej2_instances'][0];
    formEle.getInputElement('TotalCost').value = formEle.getInputElement('UnitPrice').value * formEle.getInputElement('UnitsInStock').value;
  }
  
}
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

Granular control over editing allows restriction of CRUD actions for specific rows or cells using the actionBegin event. Evaluate the requestType parameter (e.g., beginEdit, add, or delete), and conditionally set args.cancel = true to prevent undesired operations.

Example: Prevent CRUD actions for rows where the Role column equals Admin.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { EditEventArgs, EditSettingsModel, ToolbarItems } 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: 'Normal' };
        this.toolbar = ['Add', 'Edit', '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));

Perform CRUD actions programmatically

CRUD (Create, Read, Update, Delete) operations can be executed in code, providing automation and integration with custom workflows.

  • addRecord: Add a new record with optional data and index.
  • startEdit: Edit a selected row.
  • updateRow: Update a row’s data at a given index.
  • setCellValue: Update a specific cell visually (used for unbound or calculated columns; does not persist to the data source).
  • deleteRecord: Delete a selected row.

These APIs are available in both normal and dialog editing modes.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data,  columnDataType } from './datasource';
import { EditSettingsModel,  GridComponent } from '@syncfusion/ej2-angular-grids';
import { ButtonModule } from '@syncfusion/ej2-angular-grids';

@Component({
    imports: [ GridModule, ButtonModule],
    providers: [EditService, ToolbarService],
    standalone: true,
    selector: 'app-root',
    template: `
        <button ejs-button id='edit' (click)='clickEvents($event)'>Edit</button>
        <button ejs-button id='add' (click)='clickEvents($event)'>Add</button>
        <button ejs-button id='delete' (click)='clickEvents($event)'>Delete</button>
        <button ejs-button id='updaterow' (click)='clickEvents($event)'>Update Row</button>
        <button ejs-button id='updatecell' (click)='clickEvents($event)'>Update cell</button>
        <div class="control-section"  style="padding-top:20px">
            <ejs-grid #grid id="Grid" [dataSource]='data' [editSettings]='editSettings'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    width=120 [validationRules]='orderIDRules' isPrimaryKey='true'>
                    </e-column>
                    <e-column field='CustomerID' [validationRules]='customerIDRules' 
                    headerText='Customer ID' width=150></e-column>
                    <e-column field='ShipCity' headerText='Ship City' 
                    [validationRules]='cityIDRules' width=150></e-column>
                    <e-column field='ShipName' headerText='Ship Name' 
                    [validationRules]='shipIDRules' width=150></e-column>
                </e-columns>
            </ejs-grid>
        </div> `
})
export class AppComponent implements OnInit {
    
    public editSettings?: EditSettingsModel;
    public data?: object[];
    @ViewChild('grid')
    public grid?: GridComponent;
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightIDRules?: object;
    public cityIDRules?:object;
    public shipIDRules?:object;

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true ,};
        this.orderIDRules = { required: true };
        this.cityIDRules = { required: true };
        this. shipIDRules = { required: true };
        this.customerIDRules = { required: true, minLength: 5 };
        this.freightIDRules={required: true, min: 1, max:1000 }
    }
    clickEvents(args:MouseEvent){
        
        if((args.target as HTMLElement).id==='edit')
        {
          (this.grid as GridComponent).startEdit();
        }
        else if((args.target as HTMLElement).id==='add')
        {
          (this.grid as GridComponent).addRecord({ "OrderID": Math.floor(Math.random() * 100000), "CustomerID": this.generateCustomerId(), 
          "ShipCity": this.generateShipCity(), "ShipName": this.generateShipName()  });
        }
        else if((args.target as HTMLElement).id==='delete'){

           (this.grid as GridComponent).deleteRecord();
        }
        else if((args.target as HTMLElement).id==='updaterow')
        {
            (this.grid as GridComponent).updateRow(0, {OrderID:10248,CustomerID: 'RTER', ShipCity: 'America', ShipName: 'Hanari'});
        }
        else
        {
            (this.grid as GridComponent).setCellValue(((this.grid as GridComponent).currentViewData[0] as  columnDataType).OrderID,'CustomerID','Value Changed'); 
        }
    }
    generateCustomerId(): string {
        const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        let result = '';
        for (let i = 0; i < 5; i++) {
            result += characters.charAt(Math.floor(Math.random() * characters.length));
        }
        return result;
    }
    // Generate a random ShipCity
    generateShipCity(): string {
        const cities = ['London', 'Paris', 'New York', 'Tokyo', 'Berlin'];
        return cities[Math.floor(Math.random() * cities.length)];
    }
    // Generate a random Freight value
    generateFreight(): number {
        return Math.random() * 100;
    }
    // Generate a random ShipName
    generateShipName(): string {
        const names = ['Que Delícia', 'Bueno Foods', 'Island Trading', 'Laughing Bacchus Winecellars'];
        return names[Math.floor(Math.random() * names.length)];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Show confirmation dialog for deletion

The built-in confirmation dialog enhances data safety by requesting user confirmation before deleting records. Enable this dialog by setting showDeleteConfirmDialog in editSettings to true (default is false).

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'
import { SwitchModule } from '@syncfusion/ej2-angular-buttons'

import { Component, OnInit, ViewChild } from '@angular/core';
import { GridComponent, EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-grids';
import { data } from './datasource';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule,
        SwitchModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
  selector: 'app-root',
  template: `
        <div style="padding: 20px">
          <label>Enable/Disable show delete confirmation dialog</label>
          <ejs-switch id="switch1" [(checked)]="enableShowDeleteConfirmDialog" 
          (change)="toggleShowDeleteConfirmDialog()"></ejs-switch>
        </div>
        <ejs-grid #grid [dataSource]="data" [editSettings]="editSettings" [toolbar]="toolbar" height="273px">
          <e-columns>
            <e-column field="OrderID" headerText="Order ID" textAlign="Right" [validationRules]="orderIDRules"
              isPrimaryKey="true" width="100"></e-column>
            <e-column field="CustomerID" headerText="Customer ID" [validationRules]="customerIDRules" width="120"></e-column>
            <e-column field="Freight" headerText="Freight" textAlign="Right" editType="numericedit" width="120" format="C2"
              [validationRules]="freightRules"></e-column>
            <e-column field="ShipCountry" headerText="Ship Country" editType="dropdownedit" width="150"></e-column>
          </e-columns>
        </ejs-grid> `
})
export class AppComponent implements OnInit {
  
  @ViewChild('grid')
  public grid?: GridComponent;

  public data: object[] = [];
  public editSettings: EditSettingsModel = {};
  public toolbar: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];
  public orderIDRules: Object = {};
  public customerIDRules: Object = {};
  public freightRules: Object = {};
  public enableShowConfirmDialog: boolean = true;
  public enableShowDeleteConfirmDialog: boolean = false;

  ngOnInit(): void {
    this.data = data;
    this.editSettings = {
      allowEditing: true,
      allowAdding: true,
      allowDeleting: true,
      mode: 'Normal'
    };
    this.orderIDRules = { required: true, number: true };
    this.customerIDRules = { required: true };
    this.freightRules = { min: 1, max: 1000 };
  }
  toggleShowDeleteConfirmDialog(): void {
    (this.grid as GridComponent).editSettings.showDeleteConfirmDialog = this.enableShowDeleteConfirmDialog;
  }
  
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

showDeleteConfirmDialog supports all editing modes.

Display default values for columns when adding records

Preset column values streamline data entry for new records. Set defaultValue for columns in the grid configuration to ensure these fields are pre-filled in new rows.

Example using default column values:

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule,
        DropDownListModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid [dataSource]='data' [editSettings]='editSettings' 
               [toolbar]='toolbar' height='273px'>
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                        isPrimaryKey='true' [validationRules]='orderIDRules' width=100>
                        </e-column>
                        <e-column field='CustomerID' headerText='Customer ID' 
                        defaultValue= 'HANAR' [validationRules]='customerIDRules' width=120>
                        </e-column>
                        <e-column field='Freight' headerText='Freight' textAlign= 'Right' 
                        editType= 'numericedit' [validationRules]='freightIDRules' 
                        width=120 defaultValue= '1' format= 'C2'></e-column>
                        <e-column field='ShipCountry' headerText='Ship Country' 
                        editType='dropdownedit' defaultValue= 'France' width=150></e-column>
                    </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: ToolbarItems[];
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightIDRules?: object;

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
        this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
        this.orderIDRules = { required: true };
        this.customerIDRules = { required: true, minLength: 3 };
        this.freightIDRules={required: true, min: 1, max:1000 }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Delete multiple rows

Multiple row deletion is supported via the in-built toolbar or through methods.

Using the toolbar: Set the toolbar and selectionSettings.type to Multiple. Select rows and use the toolbar delete icon to remove them.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import {EditSettingsModel,ToolbarItems } from '@syncfusion/ej2-angular-grids';

@Component({
  imports: [ GridModule ],
  providers: [EditService, ToolbarService],
  standalone: true,
  selector: 'app-root',
  template: `
            <ejs-grid [dataSource]='data' [toolbar]='toolbar' [editSettings]='editSettings' 
            [selectionSettings]="selectOptions"  height='273px'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    isPrimaryKey='true' [validationRules]='orderIDRules' width=100>
                    </e-column>
                    <e-column field='CustomerID' headerText='Customer ID' 
                    [validationRules]='customerIDRules' width=120></e-column>
                    <e-column field='Freight' headerText='Freight' textAlign= 'Right'
                    editType= 'numericedit' width=120 format= 'C2'
                    [validationRules]='freightIDRules'></e-column>
                    <e-column field='ShipCountry' headerText='Ship Country' 
                    editType= 'dropdownedit' width=150></e-column>
                </e-columns>
            </ejs-grid>`,
})
export class AppComponent implements OnInit {

  public data?: object[];
  public editSettings?: EditSettingsModel;
  public toolbar?: ToolbarItems[];
  public selectOptions?: Object;
  public orderIDRules?: object;
  public customerIDRules?: object;
  public freightIDRules?: object;
 
  ngOnInit(): void {
    this.data = data;
    this.editSettings = {
      allowEditing: true,
      allowAdding: true,
      allowDeleting: true,
      mode: 'Normal',
    };
    this.orderIDRules = { required: true };
    this.customerIDRules = { required: true, minLength: 5 };
    this.freightIDRules={required: true, min: 1, max:1000 }
    this.toolbar = ['Delete'];
    this.selectOptions = { type: 'Multiple' };
  }

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

You can also delete selected records using the Delete key.

Using methods:

You can delete multiple rows programmatically by using following method.

  1. deleteRecord -This method allows you to delete a record with the given options. If the fieldname (field name of the primary key column) and data parameters are not provided, the grid will delete the selected records.

         this.grid.deleteRecord();
  2. deleteRow - Using this method, you have the ability to delete any visible row by providing the corresponding <tr> element. To achieve this, you can utilize the getSelectedRows method to retrieve the selected rows and then iterate over the rows. For each row, you can pass the <tr> element to the deleteRow method to initiate the deletion process. This approach allows you to selectively delete rows based on the <tr> elements obtained from the getSelectedRows method.

         const selectedRows: any[] = this.grid.getSelectedRows();
         selectedRows.forEach((row: HTMLTableRowElement) => {
         this.grid.deleteRow(row);
        });

Use selectionSettings.type = Multiple and consider enabling showDeleteConfirmDialog property of the editSettings to prevent accidental deletions.

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { EditSettingsModel, GridComponent } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule,
        ButtonModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
  selector: 'app-root',
  template: `
          <button ejs-button id='delete' (click)='clickDelete($event)'>Delete Multiple
          </button>
          <div class="control-section"  style="padding-top:20px">
          <ejs-grid #grid [dataSource]='data' [editSettings]='editSettings' 
          [selectionSettings]="selectOptions"  height='273px'>
            <e-columns>
              <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
              isPrimaryKey='true' [validationRules]='orderIDRules' width=100>
              </e-column>
              <e-column field='CustomerID' headerText='Customer ID' 
              [validationRules]='customerIDRules' width=120></e-column>
              <e-column field='Freight' headerText='Freight' 
              textAlign= 'Right' editType= 'numericedit' width=120 
              format= 'C2' [validationRules]='freightIDRules'></e-column>
              <e-column field='ShipCountry' headerText='Ship Country' 
              editType= 'dropdownedit' width=150></e-column>
              </e-columns>
            </ejs-grid>
            </div>`
})
export class AppComponent implements OnInit {

  public data?: object[];
  public editSettings?: EditSettingsModel;
  public selectOptions?: Object;
  @ViewChild('grid')
  public grid?: GridComponent;
  public orderIDRules?: object;
  public customerIDRules?: object;
  public freightIDRules?: object;

  ngOnInit(): void {
    this.data = data;
    this.editSettings = {
      allowEditing: true,
      allowAdding: true,
      allowDeleting: true,
    };
    this.selectOptions = { type: 'Multiple' };
    this.orderIDRules = { required: true };
    this.customerIDRules = { required: true, minLength: 5 };
    this.freightIDRules={required: true, min: 1, max:1000 }
  }
  clickDelete(args:MouseEvent) {
    const selectedRows: Element[] = (this.grid as GridComponent).getSelectedRows();
    selectedRows.forEach((row:Element) => {
      (this.grid as GridComponent).deleteRow(row as HTMLTableRowElement);
    });
}

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Add new rows at the bottom of the grid

By default, new rows are inserted at the top. To insert them at the end, set newRowPosition in editSettings to Bottom.

Example using newRowPosition:

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, ViewChild } from '@angular/core';
import { GridComponent, NewRowPosition } from '@syncfusion/ej2-angular-grids';
import { data} from './datasource';
import { ChangeEventArgs } from '@syncfusion/ej2-dropdowns';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule,
        DropDownListModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
    selector: 'app-root',
    template: `
        <div style="display: flex">
            <label style="padding: 30px 17px 0 0;"> Select new row position:</label>
            <ejs-dropdownlist  style="padding: 26px 0 0 0" index="0" width="100" 
            [dataSource]="positionData" (change)="changePosition($event)">
            </ejs-dropdownlist>
        </div>
        <div style="padding-top:20px">
            <ejs-grid #batchgrid id='Batchgrid' [dataSource]='data' allowPaging='true' [editSettings]="editSettings" [pageSettings]='pageSettings' [toolbar]='toolbar' >
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right' isPrimaryKey='true' [validationRules]='orderIDRules'></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' width='120' [validationRules]='customerIDRules'></e-column>
                    <e-column field='Freight' headerText='Freight' width='120' format='C2' textAlign='Right' editType='numericedit' [validationRules]='freightRules'></e-column>
                    <e-column field='OrderDate' headerText='Order Date' width='130' format='yMd' editType='datepickeredit' textAlign='Right'></e-column>
                    <e-column field='ShipCountry' headerText='Ship Country' width='150' editType='dropdownedit' [edit]='editparams'></e-column>
                </e-columns>
            </ejs-grid>
        </div>`
})
export class AppComponent {

    public data?: Object[];
    @ViewChild('batchgrid')
     public grid?: GridComponent;
    public editSettings?: Object;
    public toolbar?: string[];
    public orderIDRules?: Object;
    public customerIDRules?: Object;
    public freightRules?: Object;
    public editparams?: Object;
    public pageSettings?: Object;
    public positionData: { text: string; value: string }[] = [
        { text: 'Top', value: 'Top' },
        { text: 'Bottom', value: 'Bottom' },
      ];
    public ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
        this.toolbar = ['Add', 'Delete', 'Update', 'Cancel'];
        this.orderIDRules = { required: true, number: true };
        this.customerIDRules = { required: true };
        this.freightRules =  { required: true };
        this.editparams = { params: { popupHeight: '300px' } };
        this.pageSettings = {pageCount: 5};
    } 
    public changePosition(args: ChangeEventArgs): void {
       (this.grid as GridComponent).editSettings.newRowPosition= (args.value as NewRowPosition);
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

  • newRowPosition is supported for both Normal and Batch editing modes.
  • Adding with newRowPosition as Bottom displays the form at the end, but the row appears at the top if sorted accordingly.

Show add new row always in grid

The Syncfusion Grid simplifies the addition of new records by consistently presenting a blank, “add new row” form within the grid. To enable this feature, you can set the showAddNewRow property within the editSettings configuration to true. This allows for continuous addition of new records. You can display the add a new row at either the top or bottom of the grid content, depending on the newRowPosition property of editSettings. By default, the add new row is displayed at the top row of the grid content.

The following sample demonstrates how to add a new record continuously using showAddNewRow property.

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { EditSettingsModel,ToolbarItems } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule
    ],

providers: [EditService, ToolbarService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid [dataSource]='data' [editSettings]='editSettings' 
               [toolbar]='toolbar' height='315px'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    isPrimaryKey='true' [validationRules]='orderIDRules' width=100>
                    </e-column>
                    <e-column field='CustomerID' headerText='Customer ID' 
                    [validationRules]='customerIDRules' width=120></e-column>
                    <e-column field='Freight' headerText='Freight' textAlign= 'Right'
                    editType= 'numericedit' [validationRules]='freightIDRules' 
                    width=120 format= 'C2'></e-column>
                    <e-column field='ShipCountry' headerText='Ship Country' 
                    editType= 'dropdownedit' width=150></e-column>
                </e-columns>
              </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: ToolbarItems[];
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightIDRules?: object;

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, newRowPosition: 'Top', showAddNewRow: true };
        this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
        this.orderIDRules = { required: true };
        this.customerIDRules = { required: true, minLength: 5 };
        this.freightIDRules={required: true, min: 1 }

    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Save new records with Enter or the Update toolbar button.

Limitations:

  • Supported only in Inline/Normal editing mode.
  • Always appears at the top in virtual/infinite scrolling scenarios, regardless of row position configuration.
  • Incompatible with column virtualization.

Move focus to a particular cell when editing a row

Enhance the editing experience by focusing on a designated cell instead of the default (first cell) when entering edit mode. Use the recordDoubleClick event to programmatically set focus to the required cell.

Example moving focus to a specific cell:

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'



import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { EditEventArgs, EditSettingsModel, GridComponent, IEditCell, RecordDoubleClickEventArgs } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid [dataSource]='data' [editSettings]='editSettings' height='220' 
               allowPaging='true' (actionComplete)='actionComplete($event)' 
               (recordDoubleClick)='recordDoubleClick($event)'>
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                        isPrimaryKey='true' width=120 type='number' 
                        [validationRules]='orderIDRules'></e-column>
                        <e-column field='CustomerID' headerText='Customer ID' 
                        [validationRules]='customerIDRules' width=140 type='string'>
                        </e-column>
                        <e-column field='Freight' headerText='Freight' editType='numericedit' 
                        textAlign='Right' width=120 format='c2' 
                        [validationRules]='freightIDRules'></e-column>
                        <e-column field='OrderDate' headerText='Order Date' 
                        textAlign= 'Right' width=140 editType='datetimepickeredit' 
                        [format]='formatOptions' ></e-column>
                        <e-column field='ShipCountry' headerText='Ship Country' 
                        editType='dropdownedit' width=150 [edit]='params'></e-column>
                    </e-columns>
               </ejs-grid>`
})
export class AppComponent implements OnInit {
    
    public data?: object[];
    public editSettings?: EditSettingsModel;
    public formatOptions?: object;
    public params?: IEditCell;
    public fieldName: string|any = ''; // Explicitly declare the type
    @ViewChild('grid')
    public grid?: GridComponent;
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightIDRules?: object;

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, 
                            mode: "Normal" };
        this.formatOptions = { type: 'dateTime', format: 'M/d/y hh:mm a' };
        this.orderIDRules = { required: true };
        this.customerIDRules = { required: true, minLength: 5 };
        this.freightIDRules={required: true, min: 1, max:1000 }
        this.params = {
            params: {
               popupHeight: "300px"
            }
        };
    }
    actionComplete(args:EditEventArgs) {
        if (args.requestType === "beginEdit") {
            // focus the column
            ((args.form as HTMLFormElement).elements[(this.grid as GridComponent).element.getAttribute("id") + this.fieldName] as HTMLInputElement).focus();
        }
    }
    recordDoubleClick(args:RecordDoubleClickEventArgs) {
        this.fieldName = (this.grid as GridComponent).getColumnByIndex((args.cellIndex as number)).field;   
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Enable single-click editing

Activate row editing with a single click by using the startEdit and endEdit methods, in conjunction with mouse events.

To implement this feature, you need to bind the mouseup event for the Grid and, within the event handler, call the startEdit and endEdit methods based on the clicked target element. This ensures that the editing mode is triggered when clicking on a specific element within the Grid.

The following sample demonstrates how to enable editing in a single click using the mouseup event along with the load event:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, PageService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { EditSettingsModel, ToolbarItems, GridComponent } from '@syncfusion/ej2-angular-grids';
import { data } from './datasource';

@Component({
    imports: [ GridModule],
    providers: [EditService, PageService, ToolbarService],
    standalone: true,
    selector: 'app-root',
    template: `
        <ejs-grid #grid [dataSource]='data' [editSettings]='editSettings' [toolbar]='toolbar' allowPaging='true' (load)='load()'>
            <e-columns>
                <e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100 isPrimaryKey='true'></e-column>
                <e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
                <e-column field='Freight' headerText='Freight' textAlign= 'Right' width=120 format= 'C2'></e-column>
                <e-column field='ShipCountry' headerText='Ship Country' width=150></e-column>
            </e-columns>
        </ejs-grid>`
})

export class AppComponent implements OnInit {

    public data?: object[];
    public toolbar?: ToolbarItems[];
    @ViewChild('grid')
    public grid?: GridComponent;
    public editSettings?: EditSettingsModel;
    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
        this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    }
    load(){
        (this.grid as GridComponent).element.addEventListener('mouseup', (e) => {
            if ((e.target as HTMLElement).classList.contains("e-rowcell")) {
                if ((this.grid as GridComponent).isEdit){
                    (this.grid as GridComponent).endEdit();
                }
                let index: number = parseInt(((e.target as HTMLElement).getAttribute("Index") as string));
                (this.grid as GridComponent).selectRow(index);
                (this.grid as GridComponent).startEdit();
            }
        });
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Disable editing for specific rows

Editing can be restricted for designated rows using the actionBegin event. Set args.cancel = true based on custom condition checks in the event handler.

In the below demo, the rows which are having the value for ShipCountry column as France is prevented from editing.

import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, SortService, PageService } from '@syncfusion/ej2-angular-grids'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'

import { Component, OnInit } from '@angular/core';
import { data, columnDataType } from './datasource';
import { EditEventArgs, EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-grids';

@Component({
imports: [
        
        GridModule,
        DatePickerAllModule,
        FormsModule,
        TimePickerModule,
        FormsModule,
        TextBoxModule,
        MultiSelectModule,
        AutoCompleteModule
    ],

providers: [EditService, ToolbarService, SortService, PageService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid [dataSource]='data' [editSettings]='editSettings' [toolbar]='toolbar'
               (actionBegin)="actionBegin($event)" height='273px'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' [validationRules]='orderIDRules' 
                    textAlign='Right' isPrimaryKey='true' width=100></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' [validationRules]='customerIDRules' 
                    width=120></e-column>
                    <e-column field='Freight' headerText='Freight' textAlign= 'Right' editType= 'numericedit'
                    width=120 [validationRules]='freightRules' format= 'C2'></e-column>
                    <e-column field='ShipCountry' headerText='Ship Country' editType= 'dropdownedit' 
                    width=150></e-column>
                </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: ToolbarItems[];
    public orderIDRules?: object;
    public customerIDRules?: object;
    public freightRules?: Object;
    

    ngOnInit(): void {
        this.data = data;
        this.editSettings = { allowEditing: true, mode: 'Normal' };
        this.toolbar = ['Edit', 'Update', 'Cancel'];
        this.orderIDRules = { required: true };
        this.customerIDRules = { required: true };
        this.freightRules =  { min:1,max:1000 };
    }
    actionBegin(args: EditEventArgs) {
        if (args.requestType === 'beginEdit' && (args.rowData as columnDataType).ShipCountry === 'France') {
            args.cancel = true;
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));