How can I help you?
Validation in React Grid Component
14 Feb 202624 minutes to read
Data validation ensures that information entered or modified in the Grid follows specific validation rules, preventing errors and maintaining accuracy. The React Grid component in Syncfusion® provides built-in validation support to make this process easy and effective.
For basic Grid editing setup and configuration, refer to the Editing Feature Setup section first.
Column validation
Column validation applies validation rules to individual columns during edit operations, ensuring data accuracy before saving. Invalid data displays error messages and prevents saving. The FormValidator component validates data using rules defined in the validationRules property for each column.
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules = { required: true, number: true };
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const customerIDRules = { required: true, minLength: 3 };
const freightRules = { required: true, min: 1, max: 1000 };
return <GridComponent dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={265} >
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules: object = { required: true, number: true };
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const customerIDRules: object = { required: true, minLength: 3 };
const freightRules: object = { required: true, min: 1, max: 1000 };
return <GridComponent dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={265} >
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];Custom validation
Custom validation rules apply specific rules to grid columns beyond standard built-in validation. The FormValidator component applies these rules and displays error messages for invalid fields. Custom validation supports dependent field validation and numeric range validation for various application scenarios.
The following example demonstrates custom validation for the “Customer ID” column.
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const customFn = (args) => {
return args['value'].length >=5;
};
const orderIDRules = { required: true };
const customerIDRules = {
minLength: [customFn, 'Need atleast 5 letters'],
required: true
};
const freightRules = { required: true, min: 1, max: 1000 };
return <GridComponent dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={315} >
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' defaultValue='HANAR' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules}/>
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const customFn = (args: { [key: string]: string }): boolean => {
return args['value'].length >=5;
};
const orderIDRules: object = { required: true };
const customerIDRules: object = {
minLength: [customFn, 'Need atleast 5 letters'],
required: true
};
const freightRules: object = { required: true, min: 1, max: 1000 };
return <GridComponent dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={315} >
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' defaultValue='HANAR' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules}/>
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];Custom validation based on dropdown change
Dependent validation rules adjust based on selections in other columns, enabling linked column validation. The “Salary” column validation adjusts based on the “Role” column selection, ensuring both columns validate correctly together.
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { Query } from '@syncfusion/ej2-data';
import { employeeDetails } from './datasource';
function App() {
let grid;
const jobRole = [
{ role: 'TeamLead' },
{ role: 'Manager' },
{ role: 'Engineer' },
{ role: 'Sales' },
{ role: 'Support' },
];
const salaryDetails = [
{ salary: 6000 },
{ salary: 17000 },
{ salary: 18000 },
{ salary: 26000 },
{ salary: 25000 },
{ salary: 40000 },
{ salary: 35000 },
{ salary: 55000 },
{ salary: 65000 },
];
const customFn = (args) => {
const formObj = grid.editModule.formObj.element['ej2_instances'][0];
switch (window.role) {
case 'Sales':
if ((args.value >= 5000) && (args.value < 15000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
if ((args.value >= 15000 && args.value < 19000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
if ((args.value >= 25000 && args.value < 30000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'TeamLead':
if ((args.value >= 30000) && (args.value < 50000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
if ((args.value >= 50000) && (args.value < 70000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
return false;
};
const valChange = (args) => {
window.role = args.value.toString(); // Explicitly cast args.value to string
const formObj = grid.editModule.formObj.element['ej2_instances'][0];
switch (window.role) {
case 'Sales':
formObj.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
formObj.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
formObj.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'TeamLead':
formObj.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
formObj.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
}
const create = () => {
if (grid) {
let column = grid.getColumnByField('Salary');
column.validationRules = {
required: [customFn, 'Please enter valid salary'],
}
}
}
const actionBegin = (args) => {
window.role = args.rowData['Role'];
}
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const roleParams = {
params: {
allowFiltering: true,
dataSource: jobRole,
fields: { value: 'role', text: 'role' },
query: new Query(),
change: valChange
}
};
const salaryParams = {
params: {
allowFiltering: true,
dataSource: salaryDetails,
fields: { value: 'salary', text: 'salary' },
query: new Query()
}
};
return (<div>
<GridComponent id='grid' ref={g => grid = g} dataSource={employeeDetails} editSettings={editOptions}
toolbar={toolbarOptions} created={create} actionBegin={actionBegin} height={268}>
<ColumnsDirective>
<ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='Role' headerText='Role' width='160' editType='dropdownedit' edit={roleParams} />
<ColumnDirective field='Salary' headerText='Salary' width='160' editType='dropdownedit' edit={salaryParams} />
<ColumnDirective field='Address' headerText='Address' width='160' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent></div>)
};
export default App;import { ChangeEventArgs } from '@syncfusion/ej2-react-dropdowns'
import { ColumnDirective, ColumnsDirective, EditEventArgs, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems, IEditCell } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { Query } from '@syncfusion/ej2-data';
import { employeeDetails } from './datasource';
declare global {
interface Window {
role: string;
}
}
function App() {
let grid: GridComponent | null;
const jobRole: { [key: string]: Object }[] = [
{ role: 'TeamLead' },
{ role: 'Manager' },
{ role: 'Engineer' },
{ role: 'Sales' },
{ role: 'Support' },
];
const salaryDetails: { [key: string]: Object }[] = [
{ salary: 6000 },
{ salary: 17000 },
{ salary: 18000 },
{ salary: 26000 },
{ salary: 25000 },
{ salary: 40000 },
{ salary: 35000 },
{ salary: 55000 },
{ salary: 65000 },
];
const customFn = (args: { value: number }): boolean => {
const formObj = (grid as GridComponent).editModule.formObj.element['ej2_instances'][0];
switch (window.role) {
case 'Sales':
if ((args.value >= 5000) && (args.value < 15000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
if ((args.value >= 15000 && args.value < 19000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
if ((args.value >= 25000 && args.value < 30000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'TeamLead':
if ((args.value >= 30000) && (args.value < 50000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
if ((args.value >= 50000) && (args.value < 70000))
return true;
else
formObj.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
return false;
};
const valChange = (args: ChangeEventArgs) => {
window.role = (args.value.toString() as string); // Explicitly cast args.value to string
const formObj = (grid as GridComponent).editModule.formObj.element['ej2_instances'][0];
switch (window.role) {
case 'Sales':
formObj.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
formObj.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
formObj.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'TeamLead':
formObj.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
formObj.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
}
const create = (): void => {
if (grid) {
let column = (grid as GridComponent).getColumnByField('Salary');
column.validationRules = {
required: [customFn, 'Please enter valid salary'],
}
}
}
const actionBegin = (args: EditEventArgs) => {
window.role = (args.rowData as { Role: string }).Role;
}
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const roleParams: IEditCell = {
params: {
allowFiltering: true,
dataSource: jobRole,
fields: { value: 'role', text: 'role' },
query: new Query(),
change: valChange
}
};
const salaryParams: IEditCell = {
params: {
allowFiltering: true,
dataSource: salaryDetails,
fields: { value: 'salary', text: 'salary' },
query: new Query()
}
};
return (<div>
<GridComponent id='grid' ref={g => grid = g} dataSource={employeeDetails} editSettings={editOptions}
toolbar={toolbarOptions} created={create} actionBegin={actionBegin} height={268}>
<ColumnsDirective>
<ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='Role' headerText='Role' width='160' editType='dropdownedit' edit={roleParams} />
<ColumnDirective field='Salary' headerText='Salary' width='160' editType='dropdownedit' edit={salaryParams} />
<ColumnDirective field='Address' headerText='Address' width='160' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent></div>)
};
export default App;export let employeeDetails = [
{
EmployeeID: 1, Role: 'TeamLead', Salary: 35000, Address: 'Chennai'
},
{
EmployeeID: 2, Role: 'Manager', Salary: 55000, Address: 'Bangalore'
},
{
EmployeeID: 3, Role: 'Engineer', Salary: 26000, Address: 'Cochin'
},
{
EmployeeID: 4, Role: 'Sales', Salary: 6000, Address: 'Trivandrum'
},
{
EmployeeID: 5, Role: 'Support', Salary: 17000, Address: 'Delhi'
},
{
EmployeeID: 6, Role: 'TeamLead', Salary: 40000, Address: 'Chennai'
},
{
EmployeeID: 7, Role: 'Manager', Salary: 65000, Address: 'Delhi'
},
{
EmployeeID: 8, Role: 'Engineer', Salary: 26000, Address: 'Chennai'
},
{
EmployeeID: 9, Role: 'Sales', Salary: 6000, Address: 'Delhi'
},
{
EmployeeID: 10, Role: 'Support', Salary: 18000, Address: 'Delhi'
}
];export interface columnDataType {
EmployeeID: string,
Role: string,
Salary: string,
Address: string
}
export let employeeDetails: Object[] = [
{
EmployeeID: 1, Role: 'TeamLead', Salary: 35000, Address: 'Chennai'
},
{
EmployeeID: 2, Role: 'Manager', Salary: 55000, Address: 'Bangalore'
},
{
EmployeeID: 3, Role: 'Engineer', Salary: 26000, Address: 'Cochin'
},
{
EmployeeID: 4, Role: 'Sales', Salary: 6000, Address: 'Trivandrum'
},
{
EmployeeID: 5, Role: 'Support', Salary: 17000, Address: 'Delhi'
},
{
EmployeeID: 6, Role: 'TeamLead', Salary: 40000, Address: 'Chennai'
},
{
EmployeeID: 7, Role: 'Manager', Salary: 65000, Address: 'Delhi'
},
{
EmployeeID: 8, Role: 'Engineer', Salary: 26000, Address: 'Chennai'
},
{
EmployeeID: 9, Role: 'Sales', Salary: 6000, Address: 'Delhi'
},
{
EmployeeID: 10, Role: 'Support', Salary: 18000, Address: 'Delhi'
}
];Custom validation for numeric columns
Numeric column validation applies rules for numeric data such as positive values, minimum/maximum ranges, or decimal limits. This example uses “customFn” and “customFn1” functions configured through the “freightRules” object to validate numeric values. The numeric columns are bound to the change event, which calls the validate method to check the value and display error messages whenever the data changes.
import { ColumnDirective, ColumnsDirective, EditEventArgs, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let formElement;
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, newRowPosition: 'Top' };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const formatoptions = { type: 'dateTime', format: 'M/d/y hh:mm a' };
const customFn = (args) => {
return (args['value'] <= 1000);
};
const customFn1 = (args) => {
return (args['value'] >= 1);
};
const orderIDRules = { required: true };
const customerIDRules = { required: true };
const freightRules = {
required: true,
maxLength: [customFn, 'Please enter a value less than 1000'],
minLength: [customFn1, 'Please enter a value greater than 1']
};
const onChange = () => {
formElement['ej2_instances'][0].validate();
}
const shipEdit = { params: { popupHeight: '300px' } };
const freightEdit = { params: { change: onChange } }
const onActionComplete = (args) => {
if (args.requestType === "beginEdit" || args.requestType === "add") {
formElement = args.form;
}
}
return <GridComponent dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={260} actionComplete={onActionComplete}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" edit={freightEdit} validationRules={freightRules} />
<ColumnDirective field='OrderDate' headerText='OrderDate' width='120' format={formatoptions} editType='datetimepickeredit' textAlign="Right" />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' edit={shipEdit} />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;import { ColumnDirective, ColumnsDirective, EditEventArgs, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems, Page, PageSettingsModel } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let formElement: HTMLFormElement | null;
const pageSettings: PageSettingsModel = {pageSize: 5};
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, newRowPosition: 'Top' };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const formatoptions: Object = { type: 'dateTime', format: 'M/d/y hh:mm a' };
const customFn = (args: { [key: string]: number }): boolean => {
return (args['value'] <= 1000);
};
const customFn1 = (args: { [key: string]: number }): boolean => {
return (args['value'] >= 1);
};
const orderIDRules: object = { required: true };
const customerIDRules: object = { required: true };
const freightRules: object = {
required: true,
maxLength: [customFn, 'Please enter a value less than 1000'],
minLength: [customFn1, 'Please enter a value greater than 1']
};
const onChange = () => {
(formElement as HTMLFormElement)['ej2_instances'][0].validate();
}
const shipEdit: Object = { params: { popupHeight: '300px' } };
const freightEdit: Object = { params: { change: onChange } }
const onActionComplete = (args: EditEventArgs) => {
if (args.requestType === "beginEdit" || args.requestType === "add") {
formElement = args.form;
}
}
return <GridComponent dataSource={data} editSettings={editOptions} allowPaging={true} pageSettings={pageSettings}
toolbar={toolbarOptions} height={260} actionComplete={onActionComplete}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" edit={freightEdit} validationRules={freightRules} />
<ColumnDirective field='OrderDate' headerText='OrderDate' width='120' format={formatoptions} editType='datetimepickeredit' textAlign="Right" />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' edit={shipEdit} />
</ColumnsDirective>
<Inject services={[Edit, Toolbar, Page]} />
</GridComponent>
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];Dynamically add or remove validation rules from the form
Validation rules can be added or removed from input elements based on application scenarios or data conditions. The addRules method adds validation rules dynamically to input elements using the name attribute.
The following example demonstrates dynamic addition or removal of validation rules for an input field based on a checkbox selection.
import { CheckBoxComponent } from '@syncfusion/ej2-react-buttons'
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid;
let checkBox;
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules = { required: true };
const freightRules = { min: 1, max: 1000 };
let formObj;
const onActionComplete = (args) => {
if (grid) {
formObj = grid.editModule.formObj;
const customerIDRules = {
required: true,
minLength: [5, 'Customer ID should have a minimum length of 5 characters'],
};
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
if (checkBox.checked) {
// Add the custom validation rule
formObj.addRules('CustomerID', customerIDRules);
}
} else if (args.requestType === 'save' || args.requestType === 'cancel') {
formObj = undefined;
}
}
}
const checkboxChange = (args) => {
if (formObj) {
// two way binding react dynamic grid form validator rule add/remove configuration
if (args.checked) {
// Add the custom validation rule
formObj.addRules('CustomerID', {
required: true,
minLength: [5, 'Customer ID should have a minimum length of 5 characters'],
});
formObj.validate();
} else {
// Remove the custom validation rule
formObj.removeRules('CustomerID', ['required', 'minLength']);
// Add a temporary (dummy) rule to force revalidation.
// When rules are removed from an already validated field, the error message
// is not cleared automatically. This dummy rule triggers validation again
// so the field passes, removes the error element, and is then removed.
formObj.addRules('CustomerID', {required: false});
formObj.validate();
// Remove dummy validation rule after validate
formObj.removeRules('CustomerID', ['required']);
}
}
}
return (<div>
<div style=>
<CheckBoxComponent ref={c => checkBox = c} label='Enable/Disable validation rule for customerID column' checked={true} change={checkboxChange}></CheckBoxComponent>
</div>
<GridComponent ref={g => grid = g} dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={265} actionComplete={onActionComplete}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent></div>)
};
export default App;import { CheckBoxComponent, ChangeEventArgs } from '@syncfusion/ej2-react-buttons'
import { ColumnDirective, ColumnsDirective, EditEventArgs, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import { FormValidator } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid: GridComponent | null;
let checkBox: CheckBoxComponent | null;
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules: object = { required: true };
const freightRules: object = { min: 1, max: 1000 };
let formObj: FormValidator | undefined;
const onActionComplete = (args: EditEventArgs) => {
if (grid) {
formObj = (grid as GridComponent).editModule.formObj;
const customerIDRules = {
required: true,
minLength: [5, 'Customer ID should have a minimum length of 5 characters'],
};
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
if ((checkBox as CheckBoxComponent).checked) {
// Add the custom validation rule
formObj.addRules('CustomerID', customerIDRules);
}
} else if (args.requestType === 'save' || args.requestType === 'cancel') {
formObj = undefined;
}
}
}
const checkboxChange = (args: ChangeEventArgs) => {
if (formObj) {
// two way binding react dynamic grid form validator rule add/remove configuration
if (args.checked) {
// Add the custom validation rule
formObj.addRules('CustomerID', {
required: true,
minLength: [5, 'Customer ID should have a minimum length of 5 characters'],
});
formObj.validate();
} else {
// Remove the custom validation rule
formObj.removeRules('CustomerID', ['required', 'minLength']);
// Add a temporary (dummy) rule to force revalidation.
// When rules are removed from an already validated field, the error message
// is not cleared automatically. This dummy rule triggers validation again
// so the field passes, removes the error element, and is then removed.
formObj.addRules('CustomerID', {required: false});
formObj.validate();
// Remove dummy validation rule after validate
formObj.removeRules('CustomerID', ['required']);
}
}
}
return (<div style=>
<div>
<CheckBoxComponent ref={c => checkBox = c} label='Enable/Disable validation rule for customerID column' checked={true} change={checkboxChange}></CheckBoxComponent>
</div>
<GridComponent ref={g => grid = g} dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={265} actionComplete={onActionComplete}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent></div>)
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];The removeRules method removes existing validation rules from input elements when needed.
Validation error message positioning
Error message positioning customizes where validation messages appear in the grid. By default, messages display below the input field. The customPlacement event repositions messages to custom locations based on application needs.
The following example demonstrates moving validation messages to the top of the input field.
import { ColumnDirective, ColumnsDirective, getObject, GridComponent, Page } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid;
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules = { required: true, number: true };
const customerIDRules = { required: true };
const freightRules = { required: true };
const countryRules = { required: true };
const editparams = { params: { popupHeight: '200px' } };
const pageSettings = { pageCount: 5 };
const onActionComplete = (args) => {
if (args.requestType === "beginEdit" || args.requestType === "add") {
const valueError = getObject('valErrorPlacement', grid.editModule).bind(grid.editModule);
grid.editModule.formObj.customPlacement = (input, error) => {
valueError(input, error);
const element = document.getElementById(input.name + '_Error');
const tooltipWidth = element.offsetWidth;
let inputElement = null;
if (document.querySelector('#' + grid.element.id + input.name)) {
inputElement = document.querySelector('#' + grid.element.id + input.name);
} else if (document.querySelector('#' + input.name)) {
inputElement = document.querySelector('#' + input.name);
}
const inputPosition = inputElement.getBoundingClientRect();
const leftPosition = (inputPosition.left - tooltipWidth - 16).toString() + 'px'; //for right side
const topPosition = (inputPosition.top).toString() + 'px';
element.style.left = leftPosition;
element.style.top = topPosition;
element.style.position = 'fixed';
}
}
}
return (<div>
<GridComponent id='Grid' ref={g => grid = g} dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={260} actionComplete={onActionComplete} allowPaging={true} pageSettings={pageSettings}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' headerText='Customer ID' width='120' validationRules={customerIDRules} />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' validationRules={countryRules} edit={editparams} />
</ColumnsDirective>
<Inject services={[Edit, Toolbar, Page]} />
</GridComponent></div>)
};
export default App;import { ColumnDirective, ColumnsDirective, EditEventArgs, getObject, GridComponent, PageSettingsModel, Page } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid: GridComponent | null;
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules: object = { required: true, number: true };
const customerIDRules: object = { required: true };
const freightRules: object = { required: true };
const countryRules: object = { required: true };
const editparams: object = { params: { popupHeight: '200px' } };
const pageSettings: PageSettingsModel = { pageCount: 5 };
const onActionComplete = (args: EditEventArgs) => {
if (args.requestType == "beginEdit" || args.requestType == "add") {
var valueError = getObject('valErrorPlacement', (grid as GridComponent).editModule).bind((grid as GridComponent).editModule);
(grid as GridComponent).editModule.formObj.customPlacement = (input, error) => {
valueError(input, error);
debugger;
var element = document.getElementById(input.name + '_Error');
var tooltipWidth = (element as HTMLElement).offsetWidth;
var inputElement:Element|null = null;
if (document.querySelector('#' + (grid as GridComponent).element.id + input.name)) {
inputElement = document.querySelector('#' +(grid as GridComponent).element.id + input.name);
} else if (document.querySelector('#' + input.name)) {
inputElement = document.querySelector('#' + input.name);
}
var inputPosition = ( inputElement as Element).getBoundingClientRect();
var leftPosition = (inputPosition.left - tooltipWidth - 16).toString() + 'px'; //for right side
var topPosition = (inputPosition.top).toString() + 'px';
(element as HTMLElement).style.left = leftPosition;
(element as HTMLElement).style.top = topPosition;
(element as HTMLElement).style.position = 'fixed';
}
}
}
return (<div>
<GridComponent id='Grid' ref={g => grid = g} dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={260} actionComplete={onActionComplete} allowPaging={true} pageSettings={pageSettings}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' validationRules={orderIDRules} width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' headerText='Customer ID' width='120' validationRules={customerIDRules} />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules} />
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' validationRules={countryRules} edit={editparams} />
</ColumnsDirective>
<Inject services={[Edit, Toolbar, Page]} />
</GridComponent></div>)
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];CRUD error handling with custom error messages
Error handling for CRUD operations in the grid displays helpful error messages when operations fail. The actionFailure event triggers on operation failures, providing access to error messages from server responses for display.
import './App.css';
import { ColumnDirective, ColumnsDirective, GridComponent, Edit, Toolbar, Inject } from '@syncfusion/ej2-react-grids';
import { DataManager, UrlAdaptor } from "@syncfusion/ej2-data";
import React, { useState } from "react";
function App() {
const data = new DataManager({
url: 'https://localhost:****/api/Grid', // Replace your hosted link.
insertUrl: 'https://localhost:****/api/Grid/Insert',
updateUrl: 'https://localhost:****/api/Grid/Update',
removeUrl: 'https://localhost:****/api/Grid/Remove',
adaptor: new UrlAdaptor()
});
const editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbar = ['Add', 'Update', 'Delete', 'Cancel'];
const orderIDRules = { required: true };
const [errorMessage, setErrorMessage] = useState("");
const onActionFailure = (args) => {
args?.error?.[0]?.error?.json()
.then((data) => {
setErrorMessage(data.message);
})
.catch(() => {
setErrorMessage("Error occurred, but message could not be retrieved.");
});
};
return (
<>
<p style={{ color: "red", textAlign: "center", }}>{errorMessage}</p>
<GridComponent dataSource={data} editSettings={editSettings} toolbar={toolbar} actionFailure={onActionFailure} height={320}>
<ColumnsDirective>
<ColumnDirective field="OrderID" headerText="Order ID" width="120" isPrimaryKey='true' validationRules={orderIDRules} textAlign="Right" />
<ColumnDirective field="CustomerID" headerText="Customer ID" width="160" />
<ColumnDirective field="Freight" headerText="Freight" width="150" format="C2" textAlign="Right" />
<ColumnDirective field="ShipCity" headerText="Ship City" width="150" />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
</>
);
};
export default App;using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using UrlAdaptor.Server.Models;
using Syncfusion.EJ2.Base;
using Newtonsoft.Json.Linq;
namespace UrlAdaptor.Server.Controllers
{
public class GridController : Controller
{
[HttpPost]
[Route("api/[controller]")]
public object Post([FromBody] DataManagerRequest DataManagerRequest)
{
// Retrieve data from the data source (e.g., database).
IQueryable<OrdersDetails> DataSource = GetOrderData().AsQueryable();
// Get the total records count.
int totalRecordsCount = DataSource.Count();
QueryableOperation queryableOperation = new QueryableOperation(); // Initialize QueryableOperation instance.
// Handling paging operation.
if (DataManagerRequest.Skip != 0)
{
DataSource = queryableOperation.PerformSkip(DataSource, DataManagerRequest.Skip);
}
if (DataManagerRequest.Take != 0)
{
DataSource = queryableOperation.PerformTake(DataSource, DataManagerRequest.Take);
}
// Return data based on the request.
return new { result = DataSource, count = totalRecordsCount };
}
[HttpGet]
[Route("api/[controller]")]
public List<OrdersDetails> GetOrderData()
{
var data = OrdersDetails.GetAllRecords().ToList();
return data;
}
/// <summary>
/// Inserts a new data item into the data collection.
/// </summary>
/// <param name="addRecord">The order to be inserted.</param>
/// <returns>It returns the newly inserted record detail.</returns>
[HttpPost]
[Route("api/[controller]/Insert")]
public IActionResult Insert([FromBody] CRUDModel<OrdersDetails> value)
{
if (value == null)
{
return BadRequest(new { message = "Invalid data received." });
}
var existingOrder = OrdersDetails.order.FirstOrDefault(or => or.OrderID == value.value.OrderID);
if (existingOrder == null)
{
OrdersDetails.order.Insert(0, value.value);
return Ok(new { success = true, message = "Order added successfully.", data = value });
}
else
{
return BadRequest(new { success = false, message = "Duplicate values cannot be inserted." });
}
}
/// <summary>
/// Updates an existing order.
/// </summary>
/// <param name="updateRecord">The updated order details.</param>
/// <returns>It returns the updated order details.</returns>
[HttpPost]
[Route("api/[controller]/Update")]
public IActionResult Update([FromBody] CRUDModel<OrdersDetails> Order)
{
var updatedOrder = Order.value;
if (updatedOrder.OrderID > 10010 && updatedOrder.OrderID < 10030)
{
return BadRequest(new { message = "The edit action was prevented for Order IDs between 10010 and 10030." });
}
var data = OrdersDetails.GetAllRecords().FirstOrDefault(or => or.OrderID == updatedOrder.OrderID);
// Update the existing record.
data.OrderID = updatedOrder.OrderID;
data.CustomerID = updatedOrder.CustomerID;
data.ShipCity = updatedOrder.ShipCity;
data.ShipCountry = updatedOrder.ShipCountry;
return Ok(new { success = true, message = "Order updated successfully." });
}
/// <summary>
/// Deletes an order.
/// </summary>
/// <param name="deletedRecord">It contains the specific record detail which is need to be removed.</param>
/// <returns>It returns the deleted record detail.</returns>
[HttpPost]
[Route("api/[controller]/Remove")]
public IActionResult Remove([FromBody] CRUDModel<OrdersDetails> value)
{
int orderId = int.Parse(value.key.ToString());
if (orderId > 10031 && orderId < 10045)
{
return BadRequest(new { message = "The delete action was prevented for OrderIDs between 10031 and 10045" });
}
var data = OrdersDetails.GetAllRecords().FirstOrDefault(orderData => orderData.OrderID == orderId);
OrdersDetails.GetAllRecords().Remove(data);
return Ok(new { success = true, message = "Order deleted successfully." });
}
public class CRUDModel<T> where T : class
{
public string? action { get; set; }
public string? keyColumn { get; set; }
public object? key { get; set; }
public T? value { get; set; }
public List<T>? added { get; set; }
public List<T>? changed { get; set; }
public List<T>? deleted { get; set; }
public IDictionary<string, object>? @params { get; set; }
}
}
}namespace UrlAdaptor.Server.Models
{
public class OrdersDetails
{
public static List<OrdersDetails> order = new List<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;
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
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; }
}
}The following screenshot illustrates how to retrieve and display error messages when CRUD operations fail:

Preventing duplicate entries
The Grid supports prevention of duplicate rows through custom validation logic. This ensures data integrity by restricting duplicate values in the specific columns.
Three configuration steps enable this feature:
-
Custom Validation Logic: The “orderIdCustomValidation” function checks whether the entered “Order ID” already exists in the dataSource. This allows editing existing rows without triggering a duplicate error.
-
Dynamic Rule Configuration: The “orderIDRules” object enforces unique “Order ID” values. Add this rule dynamically to the form during the
saveaction. -
Event-Based Validation: The actionBegin event triggers validation. When
requestTypeequalssave, validation runs before saving. Setargs.cancel = trueif validation fails.
import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid;
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIdCustomValidation = (args) => {
return grid.dataSource.every((data) => {
return data['OrderID'] + '' !== args['value'] || data['OrderID'] === grid.editModule.editModule.args.rowData['OrderID']
});
};
const orderIDRules = {
required: true,
min: [orderIdCustomValidation, 'The entered value already exists in the column OrderID. Please enter a unique value.']
};
const customerIDRules = {
required: true
};
const freightRules = { required: true, min: 1, max: 1000 };
const actionBegin = (args) => {
if (args.requestType === 'save') {
grid.editModule.formObj.addRules('OrderID', orderIDRules); // Add form validation rules dynamically.
if (!grid.editModule.formObj.validate()) { // Check dynamically added validation rules.
args.cancel = true; // Prevent adding duplicate data action.
}
grid.editModule.formObj.removeRules('OrderID'); // Remove form validation rules dynamically.
}
}
return <GridComponent ref={(g) => grid = g } dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={268} actionBegin={actionBegin}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules}/>
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;import { ColumnDirective, ColumnsDirective, GridComponent } from '@syncfusion/ej2-react-grids';
import { Edit, EditSettingsModel, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { data } from './datasource';
function App() {
let grid: GridComponent;
const editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
const toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIdCustomValidation = (args: any): boolean => {
return grid.dataSource.every((data: Object) => {
return data['OrderID'] + '' !== args['value'] || data['OrderID'] === grid.editModule.editModule.args.rowData['OrderID']
});
};
const orderIDRules: object = {
required: true,
min: [orderIdCustomValidation, 'The entered value already exists in the column OrderID. Please enter a unique value.']
};
const customerIDRules: object = {
required: true
};
const freightRules: object = { required: true, min: 1, max: 1000 };
const actionBegin = (args: any) => {
if (args.requestType === 'save') {
grid.editModule.formObj.addRules('OrderID', orderIDRules); // Add form validation rules dynamically.
if (!grid.editModule.formObj.validate()) { // Check dynamically added validation rules.
args.cancel = true; // Prevent adding duplicate data action.
}
grid.editModule.formObj.removeRules('OrderID'); // Remove form validation rules dynamically.
}
}
return <GridComponent ref={(g) => grid = g } dataSource={data} editSettings={editOptions}
toolbar={toolbarOptions} height={268} actionBegin={actionBegin}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' width='100' textAlign="Right" isPrimaryKey={true} />
<ColumnDirective field='CustomerID' validationRules={customerIDRules} headerText='Customer ID' width='120' />
<ColumnDirective field='Freight' headerText='Freight' width='120' format="C2" editType='numericedit' textAlign="Right" validationRules={freightRules}/>
<ColumnDirective field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width='150' />
</ColumnsDirective>
<Inject services={[Edit, Toolbar]} />
</GridComponent>
};
export default App;export let data = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}
];export let data: Object[] = [
{
OrderID: 10248, CustomerID: 'VINET', Role: 'Admin', EmployeeID: 5, OrderDate: new Date(8364186e5),
ShipName: 'Vins et alcools Chevalier', ShipCity: 'Reims', ShipAddress: '59 rue de l Abbaye',
ShipRegion: 'CJ', Mask: '1111', ShipPostalCode: '51100', ShipCountry: 'France', Freight: 32.38, Verified: !0
},
{
OrderID: 10249, CustomerID: 'TOMSP', Role: 'Employee', EmployeeID: 6, OrderDate: new Date(836505e6),
ShipName: 'Toms Spezialitäten', ShipCity: 'Münster', ShipAddress: 'Luisenstr. 48',
ShipRegion: 'CJ', Mask: '2222', ShipPostalCode: '44087', ShipCountry: 'Germany', Freight: 11.61, Verified: !1
},
{
OrderID: 10250, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8367642e5),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '3333', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 65.83, Verified: !0
},
{
OrderID: 10251, CustomerID: 'VICTE', Role: 'Manager', EmployeeID: 3, OrderDate: new Date(8367642e5),
ShipName: 'Victuailles en stock', ShipCity: 'Lyon', ShipAddress: '2, rue du Commerce',
ShipRegion: 'CJ', Mask: '4444', ShipPostalCode: '69004', ShipCountry: 'France', Freight: 41.34, Verified: !0
},
{
OrderID: 10252, CustomerID: 'SUPRD', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8368506e5),
ShipName: 'Suprêmes délices', ShipCity: 'Charleroi', ShipAddress: 'Boulevard Tirou, 255',
ShipRegion: 'CJ', Mask: '5555', ShipPostalCode: 'B-6000', ShipCountry: 'Belgium', Freight: 51.3, Verified: !0
},
{
OrderID: 10253, CustomerID: 'HANAR', Role: 'Admin', EmployeeID: 3, OrderDate: new Date(836937e6),
ShipName: 'Hanari Carnes', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua do Paço, 67',
ShipRegion: 'RJ', Mask: '6666', ShipPostalCode: '05454-876', ShipCountry: 'Brazil', Freight: 58.17, Verified: !0
},
{
OrderID: 10254, CustomerID: 'CHOPS', Role: 'Employee', EmployeeID: 5, OrderDate: new Date(8370234e5),
ShipName: 'Chop-suey Chinese', ShipCity: 'Bern', ShipAddress: 'Hauptstr. 31',
ShipRegion: 'CJ', Mask: '7777', ShipPostalCode: '3012', ShipCountry: 'Switzerland', Freight: 22.98, Verified: !1
},
{
OrderID: 10255, CustomerID: 'RICSU', Role: 'Admin', EmployeeID: 9, OrderDate: new Date(8371098e5),
ShipName: 'Richter Supermarkt', ShipCity: 'Genève', ShipAddress: 'Starenweg 5',
ShipRegion: 'CJ', Mask: '8888', ShipPostalCode: '1204', ShipCountry: 'Switzerland', Freight: 148.33, Verified: !0
},
{
OrderID: 10256, CustomerID: 'WELLI', Role: 'Employee', EmployeeID: 3, OrderDate: new Date(837369e6),
ShipName: 'Wellington Importadora', ShipCity: 'Resende', ShipAddress: 'Rua do Mercado, 12',
ShipRegion: 'SP', Mask: '9999', ShipPostalCode: '08737-363', ShipCountry: 'Brazil', Freight: 13.97, Verified: !1
},
{
OrderID: 10257, CustomerID: 'HILAA', Role: 'Admin', 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', Mask: '1234', ShipPostalCode: '5022', ShipCountry: 'Venezuela', Freight: 81.91, Verified: !0
},
{
OrderID: 10258, CustomerID: 'ERNSH', Role: 'Manager', EmployeeID: 1, OrderDate: new Date(8375418e5),
ShipName: 'Ernst Handel', ShipCity: 'Graz', ShipAddress: 'Kirchgasse 6',
ShipRegion: 'CJ', Mask: '2345', ShipPostalCode: '8010', ShipCountry: 'Austria', Freight: 140.51, Verified: !0
},
{
OrderID: 10259, CustomerID: 'CENTC', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8376282e5),
ShipName: 'Centro comercial Moctezuma', ShipCity: 'México D.F.', ShipAddress: 'Sierras de Granada 9993',
ShipRegion: 'CJ', Mask: '3456', ShipPostalCode: '05022', ShipCountry: 'Mexico', Freight: 3.25, Verified: !1
},
{
OrderID: 10260, CustomerID: 'OTTIK', Role: 'Admin', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Ottilies Käseladen', ShipCity: 'Köln', ShipAddress: 'Mehrheimerstr. 369',
ShipRegion: 'CJ', Mask: '4567', ShipPostalCode: '50739', ShipCountry: 'Germany', Freight: 55.09, Verified: !0
},
{
OrderID: 10261, CustomerID: 'QUEDE', Role: 'Manager', EmployeeID: 4, OrderDate: new Date(8377146e5),
ShipName: 'Que Delícia', ShipCity: 'Rio de Janeiro', ShipAddress: 'Rua da Panificadora, 12',
ShipRegion: 'RJ', Mask: '5678', ShipPostalCode: '02389-673', ShipCountry: 'Brazil', Freight: 3.05, Verified: !1
},
{
OrderID: 10262, CustomerID: 'RATTC', Role: 'Employee', EmployeeID: 8, OrderDate: new Date(8379738e5),
ShipName: 'Rattlesnake Canyon Grocery', ShipCity: 'Albuquerque', ShipAddress: '2817 Milton Dr.',
ShipRegion: 'NM', Mask: '6789', ShipPostalCode: '87110', ShipCountry: 'USA', Freight: 48.29, Verified: !0
}];Server-side validation implementation details are available in the knowledge base article. To display validation tooltips instead of alerts, call
grid.editModule.formObj.validate()in the success callback of Ajax/Fetch operations.