Local data in React Grid component

8 Mar 202424 minutes to read

The Syncfusion Grid offers a straightforward way to bind local data, such as arrays or JSON objects, to the grid component. This feature allows you to display and manipulate data within the grid without the need for external server calls, making it particularly useful for scenarios where you’re working with static or locally stored data.

To achieve this, you can assign a JavaScript object array to the dataSource property. Additionally, you have an option to provide the local data source using an instance of the DataManager.

The following example demonstrates how to utilize the local data binding feature in the React Grid component:

import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
    return <GridComponent dataSource={data.slice(0, 7)}>
        <ColumnsDirective>
            <ColumnDirective field='OrderID' headerText='Order ID' width='120' textAlign="Right"/>
            <ColumnDirective field='CustomerID' headerText='Customer ID' width='150'/>
            <ColumnDirective field='ShipCity' headerText='Ship City' width='150'/>
            <ColumnDirective field='ShipName' headerText='Ship Name' width='150'/>
        </ColumnsDirective>
    </GridComponent>;
}
;
export default App;
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';

function App() {
    return <GridComponent dataSource={data.slice(0, 7)}>
        <ColumnsDirective>
            <ColumnDirective field='OrderID' headerText='Order ID' width='120' textAlign="Right" />
            <ColumnDirective field='CustomerID' headerText='Customer ID' width='150' />
            <ColumnDirective field='ShipCity' headerText='Ship City' width='150' />
            <ColumnDirective field='ShipName' headerText='Ship Name' width='150' />
        </ColumnsDirective>
    </GridComponent>
};
export default App;
export let data = [
    {
        OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5),
        ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
        ShipRegion: 'CJ', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
    },
    {
        OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6),
        ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
        ShipRegion: 'CJ', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
    },
    {
        OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
    },
    {
        OrderID: 10251, CustomerID: 'VICTE', EmployeeID: 3, OrderDate: new Date(8367642e5),
        ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
        ShipRegion: 'CJ', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
    },
    {
        OrderID: 10252, CustomerID: 'SUPRD', EmployeeID: 4, OrderDate: new Date(8368506e5),
        ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
        ShipRegion: 'CJ', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
    },
    {
        OrderID: 10253, CustomerID: 'HANAR', EmployeeID: 3, OrderDate: new Date(836937e6),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
    },
    {
        OrderID: 10254, CustomerID: 'CHOPS', EmployeeID: 5, OrderDate: new Date(8370234e5),
        ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
        ShipRegion: 'CJ', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
    },
    {
        OrderID: 10255, CustomerID: 'RICSU', EmployeeID: 9, OrderDate: new Date(8371098e5),
        ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
        ShipRegion: 'CJ', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
    },
    {
        OrderID: 10256, CustomerID: 'WELLI', EmployeeID: 3, OrderDate: new Date(837369e6),
        ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
        ShipRegion: 'SP', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
    },
    {
        OrderID: 10257, CustomerID: 'HILAA', EmployeeID: 4, OrderDate: new Date(8374554e5),
        ShipName: 'HILARION-Abastos', ShipCity: 'San Cristóbal', ShipAddress: 'Carrera 22 con Ave. Carlos Soublette #8-35',
        ShipRegion: 'Táchira', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
    },
    {
        OrderID: 10258, CustomerID: 'ERNSH', EmployeeID: 1, OrderDate: new Date(8375418e5),
        ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
        ShipRegion: 'CJ', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
    },
    {
        OrderID: 10259, CustomerID: 'CENTC', EmployeeID: 4, OrderDate: new Date(8376282e5),
        ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
        ShipRegion: 'CJ', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
    },
    {
        OrderID: 10260, CustomerID: 'OTTIK', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
        ShipRegion: 'CJ', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
    },
    {
        OrderID: 10261, CustomerID: 'QUEDE', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
        ShipRegion: 'RJ', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
    },
    {
        OrderID: 10262, CustomerID: 'RATTC', EmployeeID: 8, OrderDate: new Date(8379738e5),
        ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
        ShipRegion: 'NM', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
    }
];
export let data: Object[] = [
    {
        OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5),
        ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
        ShipRegion: 'CJ', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
    },
    {
        OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6),
        ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
        ShipRegion: 'CJ', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
    },
    {
        OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
    },
    {
        OrderID: 10251, CustomerID: 'VICTE', EmployeeID: 3, OrderDate: new Date(8367642e5),
        ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
        ShipRegion: 'CJ', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
    },
    {
        OrderID: 10252, CustomerID: 'SUPRD', EmployeeID: 4, OrderDate: new Date(8368506e5),
        ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
        ShipRegion: 'CJ', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
    },
    {
        OrderID: 10253, CustomerID: 'HANAR', EmployeeID: 3, OrderDate: new Date(836937e6),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
    },
    {
        OrderID: 10254, CustomerID: 'CHOPS', EmployeeID: 5, OrderDate: new Date(8370234e5),
        ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
        ShipRegion: 'CJ', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
    },
    {
        OrderID: 10255, CustomerID: 'RICSU', EmployeeID: 9, OrderDate: new Date(8371098e5),
        ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
        ShipRegion: 'CJ', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
    },
    {
        OrderID: 10256, CustomerID: 'WELLI', EmployeeID: 3, OrderDate: new Date(837369e6),
        ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
        ShipRegion: 'SP', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
    },
    {
        OrderID: 10257, CustomerID: 'HILAA', EmployeeID: 4, OrderDate: new Date(8374554e5),
        ShipName: 'HILARION-Abastos', ShipCity: 'San Cristóbal', ShipAddress: 'Carrera 22 con Ave. Carlos Soublette #8-35',
        ShipRegion: 'Táchira', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
    },
    {
        OrderID: 10258, CustomerID: 'ERNSH', EmployeeID: 1, OrderDate: new Date(8375418e5),
        ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
        ShipRegion: 'CJ', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
    },
    {
        OrderID: 10259, CustomerID: 'CENTC', EmployeeID: 4, OrderDate: new Date(8376282e5),
        ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
        ShipRegion: 'CJ', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
    },
    {
        OrderID: 10260, CustomerID: 'OTTIK', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
        ShipRegion: 'CJ', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
    },
    {
        OrderID: 10261, CustomerID: 'QUEDE', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
        ShipRegion: 'RJ', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
    },
    {
        OrderID: 10262, CustomerID: 'RATTC', EmployeeID: 8, OrderDate: new Date(8379738e5),
        ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
        ShipRegion: 'NM', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
    }];

Binding data from excel file

The Syncfusion Grid component allows you to import data from Excel files into your web application for display and manipulation within the grid. This feature streamlines the process of transferring Excel data to a web-based environment. This can be achieved by using Uploader component change event.

To import excel data in to grid, you can follow these steps:

  1. Import excel file using Uploader component.
  2. Parse the excel file data using XLSX library.
  3. Bind the JSON to the grid component.

The following example demonstrates how to import Excel data into the grid by utilizing the Uploader component’s change event along with the XLSX library:

import { L10n } from '@syncfusion/ej2-base';
import { GridComponent } from '@syncfusion/ej2-react-grids';
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import { data } from './datasource';

function App() {
  let grid;
  const path = {
    saveUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Save',
    removeUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Remove'
  };
  const dropElement = document.getElementsByClassName('control-fluid')[0];
  const parseExcel = (file) => {
    var reader = new FileReader();
    reader.onload = (e) => {
      var data = (e.target).result;
      var workbook = XLSX.read(data, { type: 'array' });
      workbook.SheetNames.forEach((sheetName) => {
        var XL_row_object = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
        grid.dataSource = XL_row_object;
      });
    };
    reader.readAsArrayBuffer(file.rawFile);
  };
  const onSuccess = (args) => {
    var files = args.file;
    if (files)
      parseExcel(files[0]);
  }
  const onRemove = () => {
    grid.dataSource = [];
  }
  return (<div>
    <UploaderComponent asyncSettings={path} removing={onRemove} dropArea={dropElement} change={onSuccess}></UploaderComponent>
    <GridComponent ref={g => grid = g}></GridComponent>
  </div>
  );
};
export default App;
import { L10n } from '@syncfusion/ej2-base';
import { GridComponent } from '@syncfusion/ej2-react-grids';
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import { data } from './datasource';
// import * as XLSX from 'xlsx';


function App() {
  let grid: GridComponent | null;
  const path: Object = {
    saveUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Save',
    removeUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Remove'
  };
  const dropElement: HTMLElement = document.getElementsByClassName('control-fluid')[0] as HTMLElement;
  const parseExcel = (file: any) => {
    var reader = new FileReader();
    reader.onload = (e) => {
      var data = ((e as any).target).result;
      var workbook = XLSX.read(data, { type: 'array' });
      workbook.SheetNames.forEach((sheetName: any) => {
        var XL_row_object = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
        (grid as GridComponent).dataSource = XL_row_object;
      });
    };
    reader.readAsArrayBuffer(file.rawFile);
  };
  const onSuccess = (args: any) => {
    var files = args.file;
    if (files)
      parseExcel(files[0]);
  }
  const onRemove = (args: any) => {
    (grid as GridComponent).dataSource = [];
  }
  return (<div>
    <UploaderComponent asyncSettings={path} removing={onRemove} dropArea={dropElement} change={onSuccess}></UploaderComponent>
    <GridComponent ref={g => grid = g}></GridComponent>
  </div>
  );
};
export default App;
export let data = [
    {
        OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5),
        ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
        ShipRegion: 'CJ', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
    },
    {
        OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6),
        ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
        ShipRegion: 'CJ', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
    },
    {
        OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
    },
    {
        OrderID: 10251, CustomerID: 'VICTE', EmployeeID: 3, OrderDate: new Date(8367642e5),
        ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
        ShipRegion: 'CJ', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
    },
    {
        OrderID: 10252, CustomerID: 'SUPRD', EmployeeID: 4, OrderDate: new Date(8368506e5),
        ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
        ShipRegion: 'CJ', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
    },
    {
        OrderID: 10253, CustomerID: 'HANAR', EmployeeID: 3, OrderDate: new Date(836937e6),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
    },
    {
        OrderID: 10254, CustomerID: 'CHOPS', EmployeeID: 5, OrderDate: new Date(8370234e5),
        ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
        ShipRegion: 'CJ', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
    },
    {
        OrderID: 10255, CustomerID: 'RICSU', EmployeeID: 9, OrderDate: new Date(8371098e5),
        ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
        ShipRegion: 'CJ', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
    },
    {
        OrderID: 10256, CustomerID: 'WELLI', EmployeeID: 3, OrderDate: new Date(837369e6),
        ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
        ShipRegion: 'SP', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
    },
    {
        OrderID: 10257, CustomerID: 'HILAA', EmployeeID: 4, OrderDate: new Date(8374554e5),
        ShipName: 'HILARION-Abastos', ShipCity: 'San Cristóbal', ShipAddress: 'Carrera 22 con Ave. Carlos Soublette #8-35',
        ShipRegion: 'Táchira', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
    },
    {
        OrderID: 10258, CustomerID: 'ERNSH', EmployeeID: 1, OrderDate: new Date(8375418e5),
        ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
        ShipRegion: 'CJ', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
    },
    {
        OrderID: 10259, CustomerID: 'CENTC', EmployeeID: 4, OrderDate: new Date(8376282e5),
        ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
        ShipRegion: 'CJ', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
    },
    {
        OrderID: 10260, CustomerID: 'OTTIK', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
        ShipRegion: 'CJ', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
    },
    {
        OrderID: 10261, CustomerID: 'QUEDE', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
        ShipRegion: 'RJ', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
    },
    {
        OrderID: 10262, CustomerID: 'RATTC', EmployeeID: 8, OrderDate: new Date(8379738e5),
        ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
        ShipRegion: 'NM', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
    }
];
export let data: Object[] = [
    {
        OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5),
        ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
        ShipRegion: 'CJ', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
    },
    {
        OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6),
        ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
        ShipRegion: 'CJ', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
    },
    {
        OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
    },
    {
        OrderID: 10251, CustomerID: 'VICTE', EmployeeID: 3, OrderDate: new Date(8367642e5),
        ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
        ShipRegion: 'CJ', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
    },
    {
        OrderID: 10252, CustomerID: 'SUPRD', EmployeeID: 4, OrderDate: new Date(8368506e5),
        ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
        ShipRegion: 'CJ', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
    },
    {
        OrderID: 10253, CustomerID: 'HANAR', EmployeeID: 3, OrderDate: new Date(836937e6),
        ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
        ShipRegion: 'RJ', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
    },
    {
        OrderID: 10254, CustomerID: 'CHOPS', EmployeeID: 5, OrderDate: new Date(8370234e5),
        ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
        ShipRegion: 'CJ', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
    },
    {
        OrderID: 10255, CustomerID: 'RICSU', EmployeeID: 9, OrderDate: new Date(8371098e5),
        ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
        ShipRegion: 'CJ', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
    },
    {
        OrderID: 10256, CustomerID: 'WELLI', EmployeeID: 3, OrderDate: new Date(837369e6),
        ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
        ShipRegion: 'SP', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
    },
    {
        OrderID: 10257, CustomerID: 'HILAA', EmployeeID: 4, OrderDate: new Date(8374554e5),
        ShipName: 'HILARION-Abastos', ShipCity: 'San Cristóbal', ShipAddress: 'Carrera 22 con Ave. Carlos Soublette #8-35',
        ShipRegion: 'Táchira', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
    },
    {
        OrderID: 10258, CustomerID: 'ERNSH', EmployeeID: 1, OrderDate: new Date(8375418e5),
        ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
        ShipRegion: 'CJ', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
    },
    {
        OrderID: 10259, CustomerID: 'CENTC', EmployeeID: 4, OrderDate: new Date(8376282e5),
        ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
        ShipRegion: 'CJ', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
    },
    {
        OrderID: 10260, CustomerID: 'OTTIK', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
        ShipRegion: 'CJ', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
    },
    {
        OrderID: 10261, CustomerID: 'QUEDE', EmployeeID: 4, OrderDate: new Date(8377146e5),
        ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
        ShipRegion: 'RJ', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
    },
    {
        OrderID: 10262, CustomerID: 'RATTC', EmployeeID: 8, OrderDate: new Date(8379738e5),
        ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
        ShipRegion: 'NM', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
    }];

Binding data and performing CRUD actions via Fetch request

The Syncfusion Grid provides a seamless way to bind data from external sources using Fetch requests, facilitating CRUD (Create, Read, Update, Delete) operations with data retrieved from a server. This feature is particularly valuable for sending data to a server for database updates and asynchronously retrieving data without refreshing the entire web page.

To achieve data binding and perform CRUD actions using Ajax requests in the Syncfusion Grid, follow these steps:

Step 1: Include the Syncfusion Grid in your HTML with necessary configurations:

    <div>
        <ButtonComponent onClick={onClick}>Bind data via Fetch</ButtonComponent>
        <GridComponent ref={g => grid = g} allowPaging={true} allowFiltering={true} editSettings={editSettings} toolbar={toolbar} actionBegin={actionBegin} actionComplete={actionComplete}>
        <ColumnsDirective>
            <ColumnDirective field='OrderID' headerText='Order ID' textAlign="Right" width='120' isPrimaryKey={true} />
            <ColumnDirective field='CustomerID' headerText='CustomerID' width='160' />
            <ColumnDirective field='ShipCity' headerText='ShipCity' textAlign="Right" width='120' />
        </ColumnsDirective>
        <Inject services={[Page, Filter, Edit, Toolbar]} />
        </GridComponent>
    </div>

Step 2: To bind data from an external Fetch request, utilize the dataSource property of the Grid. Fetch data from the server and provide it to the dataSource property using the onSuccess event of the Fetch request.

   const click = () => {
      const fetch= new Fetch("https://localhost:****/Home/Getdata", 'POST');//Use remote server host number instead ****
      fetch.send();
      fetch.onSuccess = (data: string) => {
        grid.dataSource = JSON.parse(data);
    };
    }

On the server side, there is a method named GetData within the HomeController that contains the grid’s data source. When the button is clicked, an Fetch request is sent to fetch the data from the server and bind it to the Grid component.

public class HomeController : Controller
    {        
    public ActionResult Getdata()
        {
            IEnumerable DataSource = OrdersDetails.GetAllRecords();
            return Json(DataSource);
        } 

    //create model class define the properties
    public class OrdersDetails
       {
        public OrdersDetails()
           {

           }
        public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
        {
            this.OrderID = OrderID;
            this.CustomerID = CustomerId;
            this.EmployeeID = EmployeeId;
            this.Freight = Freight;
            this.ShipCity = ShipCity;
            this.Verified = Verified;
            this.OrderDate = OrderDate;
            this.ShipName = ShipName;
            this.ShipCountry = ShipCountry;
            this.ShippedDate = ShippedDate;
            this.ShipAddress = ShipAddress;
        }
        //Render data in this method
        public static List<OrdersDetails> GetAllRecords()
        {
            List<OrdersDetails> order = new List<OrdersDetails>();
            int code = 10000;
            for (int i = 1; i < 10; i++)
            {
                order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
                order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123"));
                order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo"));
                order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7"));
                order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S."));
                code += 5;
            }
            return order;
        }

        public int? OrderID { get; set; }
        public string CustomerID { get; set; }
        public int? EmployeeID { get; set; }
        public double? Freight { get; set; }
        public string ShipCity { get; set; }
        public bool Verified { get; set; }
        public DateTime OrderDate { get; set; }
        public string ShipName { get; set; }
        public string ShipCountry { get; set; }
        public DateTime ShippedDate { get; set; }
        public string ShipAddress { get; set; }
    }    
}

Step 3: To perform CRUD actions, leverage the actionBegin event. You can cancel the default CRUD operations by utilizing the cancel argument provided by this event. This allows you to dynamically call your server-side method using Fetch, along with the relevant data received from the actionBegin event, to update your server data accordingly.

A. To add a new record using Fetch requests, follow these steps:

       let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                // Add and edit operations
                if (e.requestType == 'save' && ((e as any).action == 'add')) {
                    var editedData = (e as any).data;
                    // The default edit operation is cancelled
                    e.cancel = true;
                    // Here you can send the updated data to your server using fetch call
                    var fetch = new Fetch({
                        url: 'https://localhost:****/Home/Insert',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ value: editedData })
                    }); //Use remote server host number instead ****
                    fetch.onSuccess = () => {
                        // flag is enabled to skip this execution when grid ends add/edit
                        flag = true;
                        // The added/edited data will be saved in the Grid
                        grid.endEdit();
                    }
                    fetch.onFailure = () => {
                        // Add/edit failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    fetch.send();
                }
        }
//insert the record
    public ActionResult Insert(OrdersDetails value)
        {
            OrdersDetails.GetAllRecords().Insert(0, value);
            return Json(value);
        }

B. To edit and save a record using an Fetch request, follow these steps:

        let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                if (e.requestType == 'save' && ((e as any).action == "edit")) {
                    var editedData = (e as any).data;
                    // The default edit operation is cancelled
                    e.cancel = true;
                    // Here you can send the updated data to your server using fetch call
                    var fetch= new Fetch({
                        url: 'https://localhost:****/Home/Update',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ value: editedData })
                    });//Use remote server host number instead ****
                    fetch.onSuccess = () => {
                        // flag is enabled to skip this execution when grid ends add/edit
                        flag = true;
                        // The added/edited data will be saved in the Grid
                        grid.endEdit();
                    }
                    fetch.onFailure = () => {
                        // Add/edit failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    fetch.send();
                }        
            }
        }
//update the record
public ActionResult Update(OrdersDetails value)
        {
            var ord = value;
            OrdersDetails val = OrdersDetails.GetAllRecords().Where(or => or.OrderID == ord.OrderID).FirstOrDefault();
            val.OrderID = ord.OrderID;
            val.EmployeeID = ord.EmployeeID;
            val.CustomerID = ord.CustomerID;
            return Json(value);
        }

C. To delete a record using an Fetch request, follow these steps:

        let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                if (e.requestType == 'delete') {
                    var editedData = (e as any).data;
                    // The default delete operation is cancelled
                    e.cancel = true;
                    // Here you can send the deleted data to your server using fetch call
                    var fetch = new Fetch({
                        url: 'https://localhost:****/Home/Delete',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ key: editedData[0][grid.getPrimaryKeyFieldNames()[0]] })
                    }) //Use remote server host number instead ****
                    fetch.onSuccess = () => {
                        // flag is enabled to skip this execution when grid deletes record
                        flag = true;
                        // The deleted data will be removed in the Grid
                        grid.deleteRecord();
                    }
                    fetch.onFailure = () => {
                        // Delete failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    fetch.send();
                }
            }
    }
//Delete the record
  public ActionResult Delete(int key)
        {
            OrdersDetails.GetAllRecords().Remove(OrdersDetails.GetAllRecords().Where(or => or.OrderID == key).FirstOrDefault());
            var data = OrdersDetails.GetAllRecords();
            return Json(data);
        }

Step 4: In the Fetch success event, you have the flexibility to utilize the Grid’s endEdit and deleteRecord methods to handle the addition, editing, and deletion of corresponding data in the Grid. However, invoking these methods triggers the actionBegin event once again to save the changes in the Grid. To prevent this behavior and maintain control over the execution flow, you can employ a flag variable and manage it within the actionComplete and Fetch failure events: The following code snippet demonstrates this approach:

        const actionComplete = (e: EditEventArgs) => {
            if (e.requestType === 'save' || e.requestType === 'delete') {
                // The flag is disabled after operation is successfully performed so that it can enter the condition on next execution
                flag = false;
            }
        }

The following screenshot represents loading data when the button is clicked and CRUD operations are performed:

Fetch

Display the loading indicator with local data.

The Syncfusion Grid allows you to display a loading indicator while loading local data. This feature is useful when there is a delay in loading data from a local source, and you want to inform the you that the data is being fetched.

To display the loading indicator with local data, you need to set the showSpinner property to true. This property controls the visibility of the loading indicator.

The following example demonstrates how to display the loading indicator in the Syncfusion Grid using the load and created events:

import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { lazyLoadData } from './datasource';

function App() {
  let grid: GridComponent | null;
  const load = () => {
    setTimeout(() => {
      (grid as GridComponent).showSpinner();
    }, 200)
    setTimeout(() => {
      (grid as GridComponent).dataSource = lazyLoadData as Object[];
    }, 5000)
  }
  return (<div>
    <GridComponent ref={g => grid = g} height={315} load={load}>
      <ColumnsDirective>
        <ColumnDirective field='OrderID' headerText='OrderID' width='120' textAlign="Right" />
        <ColumnDirective field='CustomerID' headerText='CustomerID' width='150' />
        <ColumnDirective field='Quantity' headerText='Quantity' width='150' />
        <ColumnDirective field='CustomerAddress' headerText='CustomerAddress' width='150' />
      </ColumnsDirective>
    </GridComponent></div>)
};
export default App;

Binding data and performing CRUD actions via AJAX request

The Syncfusion Grid provides a seamless way to bind data from external sources using AJAX requests, facilitating CRUD (Create, Read, Update, Delete) operations with data retrieved from a server. This feature is particularly valuable for sending data to a server for database updates and asynchronously retrieving data without refreshing the entire web page

To achieve data binding and perform CRUD actions using Ajax requests in the Syncfusion Grid, follow these steps:

Step 1: Include the Syncfusion Grid in your HTML with necessary configurations:

    <div>
        <ButtonComponent onClick={onClick}>Bind data via AJAX</ButtonComponent>
        <GridComponent ref={g => grid = g} allowPaging={true} allowFiltering={true} editSettings={editSettings} toolbar={toolbar} actionBegin={actionBegin} actionComplete={actionComplete}>
            <ColumnsDirective>
                <ColumnDirective field='OrderID' headerText='Order ID' textAlign="Right" width='120' isPrimaryKey={true} />
                <ColumnDirective field='CustomerID' headerText='CustomerID' width='160' />
                <ColumnDirective field='ShipCity' headerText='ShipCity' textAlign="Right" width='120' />
            </ColumnsDirective>
            <Inject services={[Page, Filter, Edit, Toolbar]} />
        </GridComponent>
    </div>

Step 2: To bind data from an external AJAX request, utilize the dataSource property of the Grid. Fetch data from the server and provide it to the dataSource property using the onSuccess event of the AJAX request.

   const click = () => {
        const ajax = new Ajax("https://localhost:****/Home/Getdata", 'POST'); //Use remote server host number instead ****
        ajax.send();
        ajax.onSuccess = (data: string) => {
            grid.dataSource = JSON.parse(data);
        };
    }

On the server side, there is a method named GetData within the HomeController that contains the grid’s data source. When the button is clicked, an AJAX request is sent to fetch the data from the server and bind it to the Grid component.

public class HomeController : Controller
    {        
        public ActionResult Getdata()
        {
            var DataSource = OrdersDetails.GetAllRecords();
            return Json(DataSource);
        } 

        //create model class define the properties
        public class OrdersDetails
           {
             public OrdersDetails()
             {

             }
        public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
        {
            this.OrderID = OrderID;
            this.CustomerID = CustomerId;
            this.EmployeeID = EmployeeId;
            this.Freight = Freight;
            this.ShipCity = ShipCity;
            this.Verified = Verified;
            this.OrderDate = OrderDate;
            this.ShipName = ShipName;
            this.ShipCountry = ShipCountry;
            this.ShippedDate = ShippedDate;
            this.ShipAddress = ShipAddress;
        }
        //Render data in this method
        public static List<OrdersDetails> GetAllRecords()
        {
            List<OrdersDetails> order = new List<OrdersDetails>();
            int code = 10000;
            for (int i = 1; i < 10; i++)
            {
                order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
                order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123"));
                order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo"));
                order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7"));
                order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S."));
                code += 5;
            }
            return order;
        }

        public int? OrderID { get; set; }
        public string CustomerID { get; set; }
        public int? EmployeeID { get; set; }
        public double? Freight { get; set; }
        public string ShipCity { get; set; }
        public bool Verified { get; set; }
        public DateTime OrderDate { get; set; }
        public string ShipName { get; set; }
        public string ShipCountry { get; set; }
        public DateTime ShippedDate { get; set; }
        public string ShipAddress { get; set; }
    }    
}

Step 3: To perform CRUD actions, leverage the actionBegin event. You can cancel the default CRUD operations by utilizing the cancel argument provided by this event. This allows you to dynamically call your server-side method using AJAX, along with the relevant data received from the actionBegin event, to update your server data accordingly.

A. To add a new record using AJAX requests, follow these steps:

       let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                // Add and edit operations
                if (e.requestType == 'save' && ((e as any).action == 'add')) {
                    var editedData = (e as any).data;
                    // The default edit operation is cancelled
                    e.cancel = true;
                    // Here you can send the updated data to your server using AJAX call
                    var ajax = new Ajax({
                        url: 'https://localhost:****/Home/Insert',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ value: editedData })
                    });  //Use remote server host number instead ****
                    ajax.onSuccess = () => {
                        // flag is enabled to skip this execution when grid ends add/edit
                        flag = true;
                        // The added/edited data will be saved in the Grid
                        grid.endEdit();
                    }
                    ajax.onFailure = () => {
                        // Add/edit failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    ajax.send();
                }
        }
//insert the record
       public ActionResult Insert([FromBody] CRUDModel<OrdersDetails> value)
       {

           OrdersDetails.GetAllRecords().Insert(0, value.value);
           return Json(value.value);
       }

B. To edit and save a record using an AJAX request, follow these steps:

        let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                if (e.requestType == 'save' && ((e as any).action == "edit")) {
                    var editedData = (e as any).data;
                    // The default edit operation is cancelled
                    e.cancel = true;
                    // Here you can send the updated data to your server using ajax call
                    var ajax = new Ajax({
                        url: 'https://localhost:****/Home/Update',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ value: editedData })
                    }); //Use remote server host number instead ****
                    ajax.onSuccess = () => {
                        // flag is enabled to skip this execution when grid ends add/edit
                        flag = true;
                        // The added/edited data will be saved in the Grid
                        grid.endEdit();
                    }
                    ajax.onFailure = () => {
                        // Add/edit failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    ajax.send();
                }
        
            }
        }
//update the record
   public ActionResult Update([FromBody] CRUDModel<OrdersDetails> value)
    {
        var ord = value.value;
        OrdersDetails val = OrdersDetails.GetAllRecords().Where(or => or.OrderID == ord.OrderID).FirstOrDefault();
        val.OrderID = ord.OrderID;
        val.EmployeeID = ord.EmployeeID;
        val.CustomerID = ord.CustomerID;
        val.Freight = ord.Freight;
        val.OrderDate = ord.OrderDate;
        val.ShipCity = ord.ShipCity;
        val.ShipCountry = ord.ShipCountry;
        return Json(value.value);
    }

C. To delete a record using an AJAX request, follow these steps:

        let flag = false;

        const actionBegin = (e: EditEventArgs) => {
            // Initially flag needs to be false in order to enter this condition
            if (!flag) {
                if (e.requestType == 'delete') {
                    var editedData = (e as any).data;
                    // The default delete operation is cancelled
                    e.cancel = true;
                    // Here you can send the deleted data to your server using ajax call
                    var ajax = new Ajax({
                        url: 'https://localhost:****/Home/Delete',
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: JSON.stringify({ key: editedData[0][grid.getPrimaryKeyFieldNames()[0]] })
                    }) //Use remote server host number instead ****
                    ajax.onSuccess = () => {
                        // flag is enabled to skip this execution when grid deletes record
                        flag = true;
                        // The deleted data will be removed in the Grid
                        grid.deleteRecord();
                    }
                    ajax.onFailure = () => {
                        // Delete failed
                        // The flag is disabled if operation is failed so that it can enter the condition on next execution
                        flag = false;
                    }
                    ajax.send();
                }
            }
    }
//Delete the record
  public ActionResult Delete(int key)
        {
            OrdersDetails.GetAllRecords().Remove(OrdersDetails.GetAllRecords().Where(or => or.OrderID == key).FirstOrDefault());
            var data = OrdersDetails.GetAllRecords();
            return Json(data);
        }

Step 4: In the AJAX success event, you have the flexibility to utilize the Grid’s endEdit and deleteRecord methods to handle the addition, editing, and deletion of corresponding data in the Grid. However, invoking these methods triggers the actionBegin event once again to save the changes in the Grid. To prevent this behavior and maintain control over the execution flow, you can employ a flag variable and manage it within the actionComplete and AJAX failure events: The following code snippet demonstrates this approach:

        const actionComplete = (e: EditEventArgs) => {
            if (e.requestType === 'save' || e.requestType === 'delete') {
                // The flag is disabled after operation is successfully performed so that it can enter the condition on next execution
                flag = false;
            }
        }

The following screenshot represents loading data when the button is clicked and CRUD operations are performed:

Ajax

Display the loading indicator using AJAX.

The Syncfusion Grid allows you to display a loading indicator while loading data using AJAX. This feature is useful when there is a delay in loading data from data , and you want to inform the you that the data is being fetched. This is particularly beneficial when working with large datasets or under conditions of slower internet connections.

To display the loading indicator with local data, you need to set the showSpinner property to true. This property controls the visibility of the loading indicator.

The following example demonstrates how to display the loading indicator in the Syncfusion Grid using the load and created events:

import { ColumnDirective, ColumnsDirective, GridComponent, Page } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { lazyLoadData } from './datasource';

function App() {
  let grid: GridComponent | null;
  let isDataLoading = true;
  const pageSettings: object = { pageSize: 5, pageCount: 3 }
  const load = () => {
    if (isDataLoading) {
        (grid as GridComponent).showSpinner();
        isDataLoading = false;
    }
  }
  const created = () => {
    isDataLoading = true;
    const grid = grid;  // Grid instance
    const ajax = new Ajax('https://ej2services.syncfusion.com/production/web-services/api/Orders','GET');
    ajax.send();
    ajax.onSuccess = (data: string) => {
        (grid as GridComponent).dataSource = JSON.parse(data);
    };
}
  return (<div>
    <GridComponent ref={g => grid = g} height={315} allowPaging={true} pageSettings={pageSettings} load={load} created={created}>
      <ColumnsDirective>
        <ColumnDirective field='OrderID' headerText='OrderID' width='120' textAlign="Right" />
        <ColumnDirective field='CustomerID' headerText='CustomerID' width='150' />
        <ColumnDirective field='EmployeeID' headerText='EmployeeID' width='150' />
        <ColumnDirective field='ShipCountry' headerText='ShipCountry' width='150' />
      </ColumnsDirective>
      <Inject services={[Page]]} />
    </GridComponent></div>)
};
export default App;

Immutable mode 

Immutable mode in the Syncfusion Grid is designed to optimize re-rendering performance by utilizing the object reference and deep compare concept. This mode ensures that when performing Grid actions, only the modified or newly added rows are re-rendered, preventing unnecessary re-rendering of unchanged rows.

To enable this feature, you need to set the enableImmutableMode property as true.

If immutable mode is enabled, when the datasource changes, only newly added rows are regenerated or reused. Consequently, the grid’s queryCellInfo and rowDataBound events trigger only for newly generated rows, not for existing rows.

If immutable mode is not enabled, both newly added rows and existing rows are regenerated or reused when the datasource changes. As a result, the rowDataBound and queryCellInfo events trigger for both newly added and existing rows.

This feature uses the primary key value for data comparison. So, you need to provide the isPrimaryKey column.

The following example demonstrates how to enable immutable mode in an React component. When add, delete, or update actions are performed, existing rows are not regenerated or reused, ensuring efficient rendering of only the modified or newly added rows:

import { ColumnDirective, ColumnsDirective, GridComponent, Inject, Page } from '@syncfusion/ej2-react-grids';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';
import { data } from './datasource';

function App() {
  const pageSettings = { pageSize: 50 };
  let immutableInit = true;
  let init = true;
  let primaryKey = 0;
  let normalStart;
  let immutableStart;
  let immutableGrid;
  let normalGrid;
  let topBtn;
  let bottomBtn;
  let deleteBtn;
  let sortBtn;
  let pageBtn;
  const immutableBeforeDataBound = () => {
    immutableStart = new Date().getTime();
  }
  const immutableDataBound = () => {
    let val = immutableInit ? '' : new Date().getTime() - immutableStart;
    document.getElementById("immutableDelete").innerHTML =
      "Immutable rendering Time: " + "<b>" + val + "</b>" + "<b>ms</b>";
    immutableStart = 0; immutableInit = false;
  }
  const addTopEvent = () => {
    let addedRecords = [
      { 'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti' }
    ];
    let aData = addedRecords.concat(immutableGrid.dataSource);
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const addBottomEvent = () => {
    let addedRecords = [
      { 'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti' }
    ]
    let aData = (immutableGrid.dataSource).concat(addedRecords);
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const deleteEvent = () => {
    (immutableGrid.dataSource).splice(0, 5);
    normalGrid.setProperties({ dataSource: immutableGrid.dataSource });
    immutableGrid.setProperties({ dataSource: immutableGrid.dataSource });
  }
  const sortEvent = () => {
    let aData = (immutableGrid.dataSource).reverse();
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const pageEvent = () => {
    let totalPage = (immutableGrid.dataSource).length / immutableGrid.pageSettings.pageSize;
    let page = Math.floor(Math.random() * totalPage) + 1;
    normalGrid.setProperties({ pageSettings: { currentPage: page } });
    immutableGrid.setProperties({ pageSettings: { currentPage: page } });
  }
  const beforeDataBound = () => {
    normalStart = new Date().getTime();
  }
  const dataBound = () => {
    let val = init ? '' : new Date().getTime() - normalStart;
    (document.getElementById("normalDelete")).innerHTML =
      "Normal rendering Time: " + "<b>" + val + "</b>" + "<b>ms</b>";
    normalStart = 0; init = false;
  }
  return <div>
    <table>
      <tbody>
        <tr>
          <td>
            <span id="immutableDelete"></span>
          </td>
        </tr>
        <tr>
          <td>
            <span id="normalDelete"></span>
          </td>
        </tr>
        <tr>
          <td>
            <div>
              <ButtonComponent ref={topInfo => { topBtn = topInfo }} cssClass='e-info' onClick={addTopEvent}>Add 5 rows at top</ButtonComponent>
              <ButtonComponent ref={bottomInfo => { bottomBtn = bottomInfo }} cssClass='e-info' onClick={addBottomEvent}>Add 5 rows at bottom</ButtonComponent>
              <ButtonComponent ref={deleteInfo => { deleteBtn = deleteInfo }} cssClass='e-info' onClick={deleteEvent}>Delete 5 rows</ButtonComponent>
              <ButtonComponent ref={sortInfo => { sortBtn = sortInfo }} cssClass='e-info' onClick={sortEvent}>Sort Order ID</ButtonComponent>
              <ButtonComponent ref={pageInfo => { pageBtn = pageInfo }} cssClass='e-info' onClick={pageEvent}>Paging</ButtonComponent>
            </div>
          </td>
        </tr>
        <tr>
          <td>
            <span><b>Immutable Grid</b></span>
            <div style=>
              <GridComponent ref={immutable => { immutableGrid = immutable }} dataSource={data} height='250' enableImmutableMode={true} allowPaging={true} pageSettings={pageSettings} beforeDataBound={immutableBeforeDataBound} dataBound={immutableDataBound}>
                <ColumnsDirective>
                  <ColumnDirective field='OrderID' headerText='Order ID' isPrimaryKey="true" width='120' textAlign='Right'></ColumnDirective>
                  <ColumnDirective field='ProductName' headerText='Product Name' width='160'></ColumnDirective>
                  <ColumnDirective field='ProductID' headerText='Product ID' width='130' textAlign='Right' />
                  <ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
                  <ColumnDirective field='CustomerName' headerText='Customer Name' width='160'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[Page]} />
              </GridComponent>
            </div>
          </td>
        </tr>
        <tr>
          <td>
            <span><b>Normal Grid</b></span>
            <div style=>
              <GridComponent ref={normal => { normalGrid = normal }} dataSource={data} height='250' allowPaging={true} pageSettings={pageSettings} beforeDataBound={beforeDataBound} dataBound={dataBound}>
                <ColumnsDirective>
                  <ColumnDirective field='OrderID' headerText='Order ID' isPrimaryKey="true" width='120' textAlign='Right'></ColumnDirective>
                  <ColumnDirective field='ProductName' headerText='Product Name' width='160'></ColumnDirective>
                  <ColumnDirective field='ProductID' headerText='Product ID' width='130' textAlign='Right' />
                  <ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
                  <ColumnDirective field='CustomerName' headerText='Customer Name' width='160'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[Page]} />
              </GridComponent>
            </div>
          </td>
        </tr>
      </tbody>
    </table></div>
}
export default App;
import { ColumnDirective, ColumnsDirective, GridComponent, Inject, Page } from '@syncfusion/ej2-react-grids';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';
import { data } from './datasource';

function App() {
  const pageSettings: object = { pageSize: 50 };
  let immutableInit: boolean = true;
  let init: boolean = true;
  let primaryKey: number = 0;
  let normalStart: number;
  let immutableStart: number;
  let immutableGrid: GridComponent;
  let normalGrid: GridComponent;
  let topBtn: ButtonComponent;
  let bottomBtn: ButtonComponent;
  let deleteBtn: ButtonComponent;
  let sortBtn: ButtonComponent;
  let pageBtn: ButtonComponent;
  const immutableBeforeDataBound = () => {
    immutableStart = new Date().getTime();
  }
  const immutableDataBound = () => {
    let val: number | string = immutableInit ? '' : new Date().getTime() - immutableStart;
    (document.getElementById("immutableDelete") as HTMLElement).innerHTML =
      "Immutable rendering Time: " + "<b>" + val + "</b>" + "<b>ms</b>";
    immutableStart = 0; immutableInit = false;
  }
  const addTopEvent = () => {
    let addedRecords: object[] = [
      { 'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti' }
    ];
    let aData: object[] = addedRecords.concat(immutableGrid.dataSource as object[]);
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const addBottomEvent = () => {
    let addedRecords: object[] = [
      { 'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson' },
      { 'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti' }
    ]
    let aData: object[] = (immutableGrid.dataSource as object[]).concat(addedRecords);
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const deleteEvent = () => {
    (immutableGrid.dataSource as object[]).splice(0, 5);
    normalGrid.setProperties({ dataSource: immutableGrid.dataSource });
    immutableGrid.setProperties({ dataSource: immutableGrid.dataSource });
  }
  const sortEvent = () => {
    let aData: object[] = (immutableGrid.dataSource as object[]).reverse();
    normalGrid.setProperties({ dataSource: aData });
    immutableGrid.setProperties({ dataSource: aData });
  }
  const pageEvent = () => {
    let totalPage: number = (immutableGrid.dataSource as object[]).length / immutableGrid.pageSettings.pageSize;
    let page: number = Math.floor(Math.random() * totalPage) + 1;
    normalGrid.setProperties({ pageSettings: { currentPage: page } });
    immutableGrid.setProperties({ pageSettings: { currentPage: page } });
  }
  const beforeDataBound = () => {
    normalStart = new Date().getTime();
  }
  const dataBound = () => {
    let val: number | string = init ? '' : new Date().getTime() - normalStart;
    (document.getElementById("normalDelete") as HTMLElement).innerHTML =
      "Normal rendering Time: " + "<b>" + val + "</b>" + "<b>ms</b>";
    normalStart = 0; init = false;
  }
  return <div>
    <table>
      <tbody>
        <tr>
          <td>
            <span id="immutableDelete"></span>
          </td>
        </tr>
        <tr>
          <td>
            <span id="normalDelete"></span>
          </td>
        </tr>
        <tr>
          <td>
            <div>
              <ButtonComponent ref={topInfo => { topBtn = topInfo }} cssClass='e-info' onClick={addTopEvent}>Add 5 rows at top</ButtonComponent>
              <ButtonComponent ref={bottomInfo => { bottomBtn = bottomInfo }} cssClass='e-info' onClick={addBottomEvent}>Add 5 rows at bottom</ButtonComponent>
              <ButtonComponent ref={deleteInfo => { deleteBtn = deleteInfo }} cssClass='e-info' onClick={deleteEvent}>Delete 5 rows</ButtonComponent>
              <ButtonComponent ref={sortInfo => { sortBtn = sortInfo }} cssClass='e-info' onClick={sortEvent}>Sort Order ID</ButtonComponent>
              <ButtonComponent ref={pageInfo => { pageBtn = pageInfo }} cssClass='e-info' onClick={pageEvent}>Paging</ButtonComponent>
            </div>
          </td>
        </tr>
        <tr>
          <td>
            <span><b>Immutable Grid</b></span>
            <div style=>
              <GridComponent ref={immutable => { immutableGrid = immutable }} dataSource={data} height='250' enableImmutableMode={true} allowPaging={true} pageSettings={pageSettings} beforeDataBound={immutableBeforeDataBound} dataBound={immutableDataBound}>
                <ColumnsDirective>
                  <ColumnDirective field='OrderID' headerText='Order ID' isPrimaryKey="true" width='120' textAlign='Right'></ColumnDirective>
                  <ColumnDirective field='ProductName' headerText='Product Name' width='160'></ColumnDirective>
                  <ColumnDirective field='ProductID' headerText='Product ID' width='130' textAlign='Right' />
                  <ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
                  <ColumnDirective field='CustomerName' headerText='Customer Name' width='160'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[Page]} />
              </GridComponent>
            </div>
          </td>
        </tr>
        <tr>
          <td>
            <span><b>Normal Grid</b></span>
            <div style=>
              <GridComponent ref={normal => { normalGrid = normal }} dataSource={data} height='250' allowPaging={true} pageSettings={pageSettings} beforeDataBound={beforeDataBound} dataBound={dataBound}>
                <ColumnsDirective>
                  <ColumnDirective field='OrderID' headerText='Order ID' isPrimaryKey="true" width='120' textAlign='Right'></ColumnDirective>
                  <ColumnDirective field='ProductName' headerText='Product Name' width='160'></ColumnDirective>
                  <ColumnDirective field='ProductID' headerText='Product ID' width='130' textAlign='Right' />
                  <ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
                  <ColumnDirective field='CustomerName' headerText='Customer Name' width='160'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[Page]} />
              </GridComponent>
            </div>
          </td>
        </tr>
      </tbody>
    </table></div>
}
export default App;
export let data = createLazyLoadData();
function createLazyLoadData() {
    let lazyLoadData = [];
    let customerid = [
        "VINET",
        "TOMSP",
        "HANAR",
        "VICTE",
        "SUPRD",
        "HANAR",
        "CHOPS",
        "RICSU",
        "WELLI",
        "HILAA",
        "ERNSH",
        "CENTC",
        "OTTIK",
        "QUEDE",
        "RATTC",
        "ERNSH",
        "FOLKO",
        "BLONP",
        "WARTH",
        "FRANK",
        "GROSR",
        "WHITC",
        "WARTH",
        "SPLIR",
        "RATTC",
        "QUICK",
        "VINET",
        "MAGAA",
        "TORTU",
        "MORGK",
        "BERGS",
        "LEHMS",
        "BERGS",
        "ROMEY",
        "ROMEY",
        "LILAS",
        "LEHMS",
        "QUICK",
        "QUICK",
        "RICAR",
        "REGGC",
        "BSBEV",
        "COMMI",
        "QUEDE",
        "TRADH",
        "TORTU",
        "RATTC",
        "VINET",
        "LILAS",
        "BLONP",
        "HUNGO",
        "RICAR",
        "MAGAA",
        "WANDK",
        "SUPRD",
        "GODOS",
        "TORTU",
        "OLDWO",
        "ROMEY",
        "LONEP",
        "ANATR",
        "HUNGO",
        "THEBI",
        "DUMON",
        "WANDK",
        "QUICK",
        "RATTC",
        "ISLAT",
        "RATTC",
        "LONEP",
        "ISLAT",
        "TORTU",
        "WARTH",
        "ISLAT",
        "PERIC",
        "KOENE",
        "SAVEA",
        "KOENE",
        "BOLID",
        "FOLKO",
        "FURIB",
        "SPLIR",
        "LILAS",
        "BONAP",
        "MEREP",
        "WARTH",
        "VICTE",
        "HUNGO",
        "PRINI",
        "FRANK",
        "OLDWO",
        "MEREP",
        "BONAP",
        "SIMOB",
        "FRANK",
        "LEHMS",
        "WHITC",
        "QUICK",
        "RATTC",
        "FAMIA"
    ];
    let product = [
        "Chai",
        "Chang",
        "Aniseed Syrup",
        "Chef Anton's Cajun Seasoning",
        "Chef Anton's Gumbo Mix",
        "Grandma's Boysenberry Spread",
        "Uncle Bob's Organic Dried Pears",
        "Northwoods Cranberry Sauce",
        "Mishi Kobe Niku",
        "Ikura",
        "Queso Cabrales",
        "Queso Manchego La Pastora",
        "Konbu",
        "Tofu",
        "Genen Shouyu",
        "Pavlova",
        "Alice Mutton",
        "Carnarvon Tigers",
        "Teatime Chocolate Biscuits",
        "Sir Rodney's Marmalade",
        "Sir Rodney's Scones",
        "Gustaf's Knäckebröd",
        "Tunnbröd",
        "Guaraná Fantástica",
        "NuNuCa Nuß-Nougat-Creme",
        "Gumbär Gummibärchen",
        "Schoggi Schokolade",
        "Rössle Sauerkraut",
        "Thüringer Rostbratwurst",
        "Nord-Ost Matjeshering",
        "Gorgonzola Telino",
        "Mascarpone Fabioli",
        "Geitost",
        "Sasquatch Ale",
        "Steeleye Stout",
        "Inlagd Sill",
        "Gravad lax",
        "Côte de Blaye",
        "Chartreuse verte",
        "Boston Crab Meat",
        "Jack's New England Clam Chowder",
        "Singaporean Hokkien Fried Mee",
        "Ipoh Coffee",
        "Gula Malacca",
        "Rogede sild",
        "Spegesild",
        "Zaanse koeken",
        "Chocolade",
        "Maxilaku",
        "Valkoinen suklaa",
        "Manjimup Dried Apples",
        "Filo Mix",
        "Perth Pasties",
        "Tourtière",
        "Pâté chinois",
        "Gnocchi di nonna Alice",
        "Ravioli Angelo",
        "Escargots de Bourgogne",
        "Raclette Courdavault",
        "Camembert Pierrot",
        "Sirop d'érable",
        "Tarte au sucre",
        "Vegie-spread",
        "Wimmers gute Semmelknödel",
        "Louisiana Fiery Hot Pepper Sauce",
        "Louisiana Hot Spiced Okra",
        "Laughing Lumberjack Lager",
        "Scottish Longbreads",
        "Gudbrandsdalsost",
        "Outback Lager",
        "Flotemysost",
        "Mozzarella di Giovanni",
        "Röd Kaviar",
        "Longlife Tofu",
        "Rhönbräu Klosterbier",
        "Lakkalikööri",
        "Original Frankfurter grüne Soße"
    ];
    let customername = [
        "Maria",
        "Ana Trujillo",
        "Antonio Moreno",
        "Thomas Hardy",
        "Christina Berglund",
        "Hanna Moos",
        "Frédérique Citeaux",
        "Martín Sommer",
        "Laurence Lebihan",
        "Elizabeth Lincoln",
        "Victoria Ashworth",
        "Patricio Simpson",
        "Francisco Chang",
        "Yang Wang",
        "Pedro Afonso",
        "Elizabeth Brown",
        "Sven Ottlieb",
        "Janine Labrune",
        "Ann Devon",
        "Roland Mendel",
        "Aria Cruz",
        "Diego Roel",
        "Martine Rancé",
        "Maria Larsson",
        "Peter Franken",
        "Carine Schmitt",
        "Paolo Accorti",
        "Lino Rodriguez",
        "Eduardo Saavedra",
        "José Pedro Freyre",
        "André Fonseca",
        "Howard Snyder",
        "Manuel Pereira",
        "Mario Pontes",
        "Carlos Hernández",
        "Yoshi Latimer",
        "Patricia McKenna",
        "Helen Bennett",
        "Philip Cramer",
        "Daniel Tonini",
        "Annette Roulet",
        "Yoshi Tannamuri",
        "John Steel",
        "Renate Messner",
        "Jaime Yorres",
        "Carlos González",
        "Felipe Izquierdo",
        "Fran Wilson",
        "Giovanni Rovelli",
        "Catherine Dewey",
        "Jean Fresnière",
        "Alexander Feuer",
        "Simon Crowther",
        "Yvonne Moncada",
        "Rene Phillips",
        "Henriette Pfalzheim",
        "Marie Bertrand",
        "Guillermo Fernández",
        "Georg Pipps",
        "Isabel de Castro",
        "Bernardo Batista",
        "Lúcia Carvalho",
        "Horst Kloss",
        "Sergio Gutiérrez",
        "Paula Wilson",
        "Maurizio Moroni",
        "Janete Limeira",
        "Michael Holz",
        "Alejandra Camino",
        "Jonas Bergulfsen",
        "Jose Pavarotti",
        "Hari Kumar",
        "Jytte Petersen",
        "Dominique Perrier",
        "Art Braunschweiger",
        "Pascale Cartrain",
        "Liz Nixon",
        "Liu Wong",
        "Karin Josephs",
        "Miguel Angel Paolino",
        "Anabela Domingues",
        "Helvetius Nagy",
        "Palle Ibsen",
        "Mary Saveley",
        "Paul Henriot",
        "Rita Müller",
        "Pirkko Koskitalo",
        "Paula Parente",
        "Karl Jablonski",
        "Matti Karttunen",
        "Zbyszek Piestrzeniewicz"
    ];
    let customeraddress = [
        "507 - 20th Ave. E.\r\nApt. 2A",
        "908 W. Capital Way",
        "722 Moss Bay Blvd.",
        "4110 Old Redmond Rd.",
        "14 Garrett Hill",
        "Coventry House\r\nMiner Rd.",
        "Edgeham Hollow\r\nWinchester Way",
        "4726 - 11th Ave. N.E.",
        "7 Houndstooth Rd.",
        "59 rue de l'Abbaye",
        "Luisenstr. 48",
        "908 W. Capital Way",
        "722 Moss Bay Blvd.",
        "4110 Old Redmond Rd.",
        "14 Garrett Hill",
        "Coventry House\r\nMiner Rd.",
        "Edgeham Hollow\r\nWinchester Way",
        "7 Houndstooth Rd.",
        "2817 Milton Dr.",
        "Kirchgasse 6",
        "Sierras de Granada 9993",
        "Mehrheimerstr. 369",
        "Rua da Panificadora, 12",
        "2817 Milton Dr.",
        "Mehrheimerstr. 369"
    ];
    let quantityperunit = [
        "10 boxes x 20 bags",
        "24 - 12 oz bottles",
        "12 - 550 ml bottles",
        "48 - 6 oz jars",
        "36 boxes",
        "12 - 8 oz jars",
        "12 - 1 lb pkgs.",
        "12 - 12 oz jars",
        "18 - 500 g pkgs.",
        "12 - 200 ml jars",
        "1 kg pkg.",
        "10 - 500 g pkgs.",
        "2 kg box",
        "40 - 100 g pkgs.",
        "24 - 250 ml bottles",
        "32 - 500 g boxes",
        "20 - 1 kg tins",
        "16 kg pkg.",
        "10 boxes x 12 pieces",
        "30 gift boxes",
        "24 pkgs. x 4 pieces",
        "24 - 500 g pkgs.",
        "12 - 250 g pkgs.",
        "12 - 355 ml cans",
        "20 - 450 g glasses",
        "100 - 250 g bags"
    ];
    let orderID = 10248;
    let k = 1;
    for (let i = 0; i < 1000; i++) {
        k = k > 9 ? 1 : k;
        lazyLoadData.push({
            OrderID: orderID + i,
            CustomerID: customerid[Math.floor(Math.random() * customerid.length)],
            CustomerName: customername[Math.floor(Math.random() * customername.length)],
            CustomerAddress: customeraddress[Math.floor(Math.random() * customeraddress.length)],
            ProductName: product[Math.floor(Math.random() * product.length)],
            ProductID: i,
            Quantity: quantityperunit[Math.floor(Math.random() * quantityperunit.length)],
            Id: k
        });
        k++;
    }
    return lazyLoadData;
}
export let data: Object[] = createLazyLoadData();

function createLazyLoadData() {
  let lazyLoadData: Object[] = [];
  let customerid: string[] = [
    "VINET",
    "TOMSP",
    "HANAR",
    "VICTE",
    "SUPRD",
    "HANAR",
    "CHOPS",
    "RICSU",
    "WELLI",
    "HILAA",
    "ERNSH",
    "CENTC",
    "OTTIK",
    "QUEDE",
    "RATTC",
    "ERNSH",
    "FOLKO",
    "BLONP",
    "WARTH",
    "FRANK",
    "GROSR",
    "WHITC",
    "WARTH",
    "SPLIR",
    "RATTC",
    "QUICK",
    "VINET",
    "MAGAA",
    "TORTU",
    "MORGK",
    "BERGS",
    "LEHMS",
    "BERGS",
    "ROMEY",
    "ROMEY",
    "LILAS",
    "LEHMS",
    "QUICK",
    "QUICK",
    "RICAR",
    "REGGC",
    "BSBEV",
    "COMMI",
    "QUEDE",
    "TRADH",
    "TORTU",
    "RATTC",
    "VINET",
    "LILAS",
    "BLONP",
    "HUNGO",
    "RICAR",
    "MAGAA",
    "WANDK",
    "SUPRD",
    "GODOS",
    "TORTU",
    "OLDWO",
    "ROMEY",
    "LONEP",
    "ANATR",
    "HUNGO",
    "THEBI",
    "DUMON",
    "WANDK",
    "QUICK",
    "RATTC",
    "ISLAT",
    "RATTC",
    "LONEP",
    "ISLAT",
    "TORTU",
    "WARTH",
    "ISLAT",
    "PERIC",
    "KOENE",
    "SAVEA",
    "KOENE",
    "BOLID",
    "FOLKO",
    "FURIB",
    "SPLIR",
    "LILAS",
    "BONAP",
    "MEREP",
    "WARTH",
    "VICTE",
    "HUNGO",
    "PRINI",
    "FRANK",
    "OLDWO",
    "MEREP",
    "BONAP",
    "SIMOB",
    "FRANK",
    "LEHMS",
    "WHITC",
    "QUICK",
    "RATTC",
    "FAMIA"
  ];

  let product: string[] = [
    "Chai",
    "Chang",
    "Aniseed Syrup",
    "Chef Anton's Cajun Seasoning",
    "Chef Anton's Gumbo Mix",
    "Grandma's Boysenberry Spread",
    "Uncle Bob's Organic Dried Pears",
    "Northwoods Cranberry Sauce",
    "Mishi Kobe Niku",
    "Ikura",
    "Queso Cabrales",
    "Queso Manchego La Pastora",
    "Konbu",
    "Tofu",
    "Genen Shouyu",
    "Pavlova",
    "Alice Mutton",
    "Carnarvon Tigers",
    "Teatime Chocolate Biscuits",
    "Sir Rodney's Marmalade",
    "Sir Rodney's Scones",
    "Gustaf's Knäckebröd",
    "Tunnbröd",
    "Guaraná Fantástica",
    "NuNuCa Nuß-Nougat-Creme",
    "Gumbär Gummibärchen",
    "Schoggi Schokolade",
    "Rössle Sauerkraut",
    "Thüringer Rostbratwurst",
    "Nord-Ost Matjeshering",
    "Gorgonzola Telino",
    "Mascarpone Fabioli",
    "Geitost",
    "Sasquatch Ale",
    "Steeleye Stout",
    "Inlagd Sill",
    "Gravad lax",
    "Côte de Blaye",
    "Chartreuse verte",
    "Boston Crab Meat",
    "Jack's New England Clam Chowder",
    "Singaporean Hokkien Fried Mee",
    "Ipoh Coffee",
    "Gula Malacca",
    "Rogede sild",
    "Spegesild",
    "Zaanse koeken",
    "Chocolade",
    "Maxilaku",
    "Valkoinen suklaa",
    "Manjimup Dried Apples",
    "Filo Mix",
    "Perth Pasties",
    "Tourtière",
    "Pâté chinois",
    "Gnocchi di nonna Alice",
    "Ravioli Angelo",
    "Escargots de Bourgogne",
    "Raclette Courdavault",
    "Camembert Pierrot",
    "Sirop d'érable",
    "Tarte au sucre",
    "Vegie-spread",
    "Wimmers gute Semmelknödel",
    "Louisiana Fiery Hot Pepper Sauce",
    "Louisiana Hot Spiced Okra",
    "Laughing Lumberjack Lager",
    "Scottish Longbreads",
    "Gudbrandsdalsost",
    "Outback Lager",
    "Flotemysost",
    "Mozzarella di Giovanni",
    "Röd Kaviar",
    "Longlife Tofu",
    "Rhönbräu Klosterbier",
    "Lakkalikööri",
    "Original Frankfurter grüne Soße"
  ];

  let customername: string[] = [
    "Maria",
    "Ana Trujillo",
    "Antonio Moreno",
    "Thomas Hardy",
    "Christina Berglund",
    "Hanna Moos",
    "Frédérique Citeaux",
    "Martín Sommer",
    "Laurence Lebihan",
    "Elizabeth Lincoln",
    "Victoria Ashworth",
    "Patricio Simpson",
    "Francisco Chang",
    "Yang Wang",
    "Pedro Afonso",
    "Elizabeth Brown",
    "Sven Ottlieb",
    "Janine Labrune",
    "Ann Devon",
    "Roland Mendel",
    "Aria Cruz",
    "Diego Roel",
    "Martine Rancé",
    "Maria Larsson",
    "Peter Franken",
    "Carine Schmitt",
    "Paolo Accorti",
    "Lino Rodriguez",
    "Eduardo Saavedra",
    "José Pedro Freyre",
    "André Fonseca",
    "Howard Snyder",
    "Manuel Pereira",
    "Mario Pontes",
    "Carlos Hernández",
    "Yoshi Latimer",
    "Patricia McKenna",
    "Helen Bennett",
    "Philip Cramer",
    "Daniel Tonini",
    "Annette Roulet",
    "Yoshi Tannamuri",
    "John Steel",
    "Renate Messner",
    "Jaime Yorres",
    "Carlos González",
    "Felipe Izquierdo",
    "Fran Wilson",
    "Giovanni Rovelli",
    "Catherine Dewey",
    "Jean Fresnière",
    "Alexander Feuer",
    "Simon Crowther",
    "Yvonne Moncada",
    "Rene Phillips",
    "Henriette Pfalzheim",
    "Marie Bertrand",
    "Guillermo Fernández",
    "Georg Pipps",
    "Isabel de Castro",
    "Bernardo Batista",
    "Lúcia Carvalho",
    "Horst Kloss",
    "Sergio Gutiérrez",
    "Paula Wilson",
    "Maurizio Moroni",
    "Janete Limeira",
    "Michael Holz",
    "Alejandra Camino",
    "Jonas Bergulfsen",
    "Jose Pavarotti",
    "Hari Kumar",
    "Jytte Petersen",
    "Dominique Perrier",
    "Art Braunschweiger",
    "Pascale Cartrain",
    "Liz Nixon",
    "Liu Wong",
    "Karin Josephs",
    "Miguel Angel Paolino",
    "Anabela Domingues",
    "Helvetius Nagy",
    "Palle Ibsen",
    "Mary Saveley",
    "Paul Henriot",
    "Rita Müller",
    "Pirkko Koskitalo",
    "Paula Parente",
    "Karl Jablonski",
    "Matti Karttunen",
    "Zbyszek Piestrzeniewicz"
  ];

  let customeraddress: string[] = [
    "507 - 20th Ave. E.\r\nApt. 2A",
    "908 W. Capital Way",
    "722 Moss Bay Blvd.",
    "4110 Old Redmond Rd.",
    "14 Garrett Hill",
    "Coventry House\r\nMiner Rd.",
    "Edgeham Hollow\r\nWinchester Way",
    "4726 - 11th Ave. N.E.",
    "7 Houndstooth Rd.",
    "59 rue de l'Abbaye",
    "Luisenstr. 48",
    "908 W. Capital Way",
    "722 Moss Bay Blvd.",
    "4110 Old Redmond Rd.",
    "14 Garrett Hill",
    "Coventry House\r\nMiner Rd.",
    "Edgeham Hollow\r\nWinchester Way",
    "7 Houndstooth Rd.",
    "2817 Milton Dr.",
    "Kirchgasse 6",
    "Sierras de Granada 9993",
    "Mehrheimerstr. 369",
    "Rua da Panificadora, 12",
    "2817 Milton Dr.",
    "Mehrheimerstr. 369"
  ];

  let quantityperunit: string[] = [
    "10 boxes x 20 bags",
    "24 - 12 oz bottles",
    "12 - 550 ml bottles",
    "48 - 6 oz jars",
    "36 boxes",
    "12 - 8 oz jars",
    "12 - 1 lb pkgs.",
    "12 - 12 oz jars",
    "18 - 500 g pkgs.",
    "12 - 200 ml jars",
    "1 kg pkg.",
    "10 - 500 g pkgs.",
    "2 kg box",
    "40 - 100 g pkgs.",
    "24 - 250 ml bottles",
    "32 - 500 g boxes",
    "20 - 1 kg tins",
    "16 kg pkg.",
    "10 boxes x 12 pieces",
    "30 gift boxes",
    "24 pkgs. x 4 pieces",
    "24 - 500 g pkgs.",
    "12 - 250 g pkgs.",
    "12 - 355 ml cans",
    "20 - 450 g glasses",
    "100 - 250 g bags"
  ];

  let orderID: number = 10248;
  let k: number = 1;
  for (let i: number = 0; i < 1000; i++) {
    k = k > 9 ? 1 : k;
    lazyLoadData.push({
      OrderID: orderID + i,
      CustomerID: customerid[Math.floor(Math.random() * customerid.length)],
      CustomerName:
        customername[Math.floor(Math.random() * customername.length)],
      CustomerAddress:
        customeraddress[Math.floor(Math.random() * customeraddress.length)],
      ProductName: product[Math.floor(Math.random() * product.length)],
      ProductID: i,
      Quantity:
        quantityperunit[Math.floor(Math.random() * quantityperunit.length)],
      Id: k
    });
    k++;
  }
  return lazyLoadData;
}

Limitations

The following features are not supported in the immutable mode:

  • Frozen rows and columns
  • Grouping
  • Row Template
  • Detail Template
  • Hierarchy Grid
  • Scrolling
  • Virtual scroll
  • Infinite scroll
  • Column reorder
  • Rows, column spanning
  • Pdf export, Excel export, Print
  • Column Resize
  • Drag and drop
  • Coulumn template
  • Column chooser
  • Clipboard
  • AutoFit
  • Flitering