Search results

Editing

The TreeGrid component has options to dynamically insert, delete and update records. Editing feature is enabled by using editSettings property and it requires a primary key column for CRUD operations. To define the primary key, set columns.isPrimaryKey to true in particular column.

To use CRUD, inject the Edit module in treegrid.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, EditSettingsModel, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Inject } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell'
    };

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='priority' headerText='Priority' width='90' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Inject } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell'
        };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='priority' headerText='Priority' width='90'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Toolbar with edit option

The treegrid toolbar has the built-in items to execute Editing actions. You can define this by using the toolbar property.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, EditSettingsModel, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Inject, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell'
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='priority' headerText='Priority' width='90' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Inject, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell'
        };
        this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='priority' headerText='Priority' width='90'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Cell edit type and its params

The columns.editType is used to customize the edit type of the particular column. You can set the columns.editType based on data type of the column.

Also, you can customize model of the columns.editType component through the columns.edit.params.

The following table describes cell edit type component and their corresponding edit params of the column.

Component Example
NumericTextBox params: { decimals: 2, value: 5 }
TextBox -
DropDownList params: { value: ‘Germany’ }
Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { IEditCell } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Row' };
    public format: any = {type:'dateTime', format:'M/d/y hh:mm a'};
    public toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];

    public datetimeParams: IEditCell = { params: { format: 'M/d/y hh:mm a' } };
    public numericParams: IEditCell = { params: { format: 'n' } };

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='100' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' editType= 'stringedit'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='180' textAlign='Right' edit={this.datetimeParams} editType='datetimepickeredit' format={this.format} />
              <ColumnDirective field='approved' headerText='Approved' width='110' textAlign='Right' editType='booleanedit' type='boolean' displayAsCheckBox={true} />
              <ColumnDirective field='progress' headerText='Progress' textAlign='Right' width='120' editType='numericedit' edit={this.numericParams} />
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Row' };
        this.format = { type: 'dateTime', format: 'M/d/y hh:mm a' };
        this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
        this.datetimeParams = { params: { format: 'M/d/y hh:mm a' } };
        this.numericParams = { params: { format: 'n' } };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='100' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' editType='stringedit'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='180' textAlign='Right' edit={this.datetimeParams} editType='datetimepickeredit' format={this.format}/>
              <ColumnDirective field='approved' headerText='Approved' width='110' textAlign='Right' editType='booleanedit' type='boolean' displayAsCheckBox={true}/>
              <ColumnDirective field='progress' headerText='Progress' textAlign='Right' width='120' editType='numericedit' edit={this.numericParams}/>
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

If edit type is not defined in the column, then it will be considered as the stringedit type (Textbox component).

Cell Edit Template

The cell edit template is used to add a custom component for a particular column by invoking the following functions:

  • create - It is used to create the element at time of initialization.

  • write - It is used to create custom component or assign default value at time of editing.

  • read - It is used to read the value from component at time of save.

  • destroy - It is used to destroy the component.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { DataManager } from '@syncfusion/ej2-data';
import { AutoComplete } from '@syncfusion/ej2-dropdowns';
import { IEditCell } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Column, Edit, EditSettingsModel, Toolbar, ToolbarItems, TreeGrid } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public elem: HTMLElement;
    public autoCompleteobj: AutoComplete;
    public treegridObj: TreeGrid | null;

    public editOptions: EditSettingsModel = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Cell', newRowPosition: 'Below' };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public editTemplate : IEditCell = {
        create:()=>{
            this.elem = document.createElement('input');
            return this.elem;
        },
        destroy:()=>{
            this.autoCompleteobj.destroy();
        },
        read:()=>{
            return this.autoCompleteobj.value;
        },
        write:(args:{rowData: object, column: Column})=>{
            if (this.treegridObj) {
                this.autoCompleteobj = new AutoComplete({
                    dataSource: new DataManager(this.treegridObj.grid.dataSource as object[]),
                    fields: { value: 'taskName' },
                    value: args.rowData[args.column.field]
                });
                this.autoCompleteobj.appendTo(this.elem);
            }
    }};


    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks'
            height='400' editSettings={this.editOptions} toolbar={this.toolbarOptions}
            ref={treegrid=> this.treegridObj = treegrid}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='100' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' editType= 'stringedit' edit={this.editTemplate}/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { DataManager } from '@syncfusion/ej2-data';
import { AutoComplete } from '@syncfusion/ej2-dropdowns';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Cell', newRowPosition: 'Below' };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
        this.editTemplate = {
            create: () => {
                this.elem = document.createElement('input');
                return this.elem;
            },
            destroy: () => {
                this.autoCompleteobj.destroy();
            },
            read: () => {
                return this.autoCompleteobj.value;
            },
            write: (args) => {
                if (this.treegridObj) {
                    this.autoCompleteobj = new AutoComplete({
                        dataSource: new DataManager(this.treegridObj.grid.dataSource),
                        fields: { value: 'taskName' },
                        value: args.rowData[args.column.field]
                    });
                    this.autoCompleteobj.appendTo(this.elem);
                }
            }
        };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='400' editSettings={this.editOptions} toolbar={this.toolbarOptions} ref={treegrid => this.treegridObj = treegrid}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='100' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' editType='stringedit' edit={this.editTemplate}/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Edit Modes

TreeGrid supports the following types of edit modes, they are:

  • Cell
  • Row
  • Dialog

Cell

In Cell edit mode, when you double click on a cell, it is changed to edit state. You can change the cell value and save to the data source. To enable Cell edit, set the editSettings.mode as Cell.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{

    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell',
        newRowPosition: 'Below'
    };

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks'
             height='270' editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell',
            newRowPosition: 'Below'
        };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Cell edit mode is default mode of editing.

Row

In Row edit mode, when you start editing the currently selected record, the entire row is changed to edit state. You can change the cell values of the row and save edited data to the data source. To enable Row edit, set the editSettings.mode as Row.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{

    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Row'
    };
    public toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks'
             height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Row'
        };
        this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Dialog

In Dialog edit mode, when you start editing the currently selected row, data will be shown on a dialog. You can change the cell values and save edited data to the data source. To enable Dialog edit, set the editSettings.mode as Dialog.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{

    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Dialog'
    };
    public toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks'
         height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Dialog'
        };
        this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Dialog template

The dialog template editing provides an option to customize the default behavior of dialog editing. Using the dialog template, you can render your own editors by defining the editSettings.mode as Dialog and template as SCRIPT element ID or HTML string which holds the template.

In some cases, you need to add the new field editors in the dialog which are not present in the column model. In that situation, the dialog template will help you to customize the default edit dialog.

In the following sample, treegrid enabled with dialog template editing.

Source
Preview
App.tsx
template.tsx
orderModel.tsx
App.css.jsx
App.jsx
index.jsx
orderModel.jsx
template.jsx
import { setValue } from '@syncfusion/ej2-base';
import { DialogEditEventArgs } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems, TreeGrid } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
import { IOrderModel } from './orderModel';
import { DialogFormTemplate } from './template';

export default class App extends React.Component<{}, {}>{
    public treegrid: TreeGrid | null;
    public toolbarOptions: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Dialog',
        template: this.dialogTemplate.bind(this)
    };

    public dialogTemplate(props: IOrderModel): any {
        const obj = [props, this.treegrid];
        return (<DialogFormTemplate {...obj} />);
    }
    public actionComplete(args: DialogEditEventArgs) {
       if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
           // Add Validation Rules
            const form: HTMLFormElement = args.form as HTMLFormElement;
            form.ej2_instances[0].addRules('progress', {max: 100});
            if (args.requestType === 'beginEdit') {
                (form.elements.namedItem('taskName') as HTMLInputElement).focus();
            }
       }
    }

    public actionBegin (args: DialogEditEventArgs) {
        if (args.requestType === 'save') {
            // cast string to integer value.
            const val: string = ((args.form as HTMLFormElement)
                .querySelector("#progress") as HTMLInputElement).value;
            setValue('data.progress', parseFloat(val), args);
        }
    }

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
             editSettings={this.editOptions} toolbar={this.toolbarOptions} ref={g=> this.treegrid = g}
              actionBegin={this.actionBegin} actionComplete={this.actionComplete}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { DataUtil } from '@syncfusion/ej2-data';
import { CheckBoxComponent } from '@syncfusion/ej2-react-buttons';
import { DatePickerComponent } from '@syncfusion/ej2-react-calendars';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import { sampleData as orderData } from './datasource';
import { IOrderModel } from './orderModel';

export class DialogFormTemplate extends React.Component<{}, {}> {
    private priorityData: any = DataUtil.distinct(orderData, 'priority', true );
    constructor(props: any) {
        super(props);
        this.state = Object.assign({}, props[0]);
    }

    public onChange(args: React.ChangeEvent) {
        this.setState({[(args.target as HTMLInputElement).name]: (args.target as HTMLInputElement).value});
    }

    public render(): any {
        this.onChange = this.onChange.bind(this);
        const data: IOrderModel = this.state;
        return (<div>
            <div className="form-row">
                <div className="form-group col-md-6">
                <div className="e-float-input e-control-wrapper">
                        <input id="taskID" name="taskID" disabled={!data.isAdd} type="text" value={data.taskID} onChange={this.onChange} />
                        <span className="e-float-line"/>
                        <label className="e-float-text e-label-top">Task ID</label>
                    </div>

                </div>
                <div className="form-group col-md-6">
                <div className="e-float-input e-control-wrapper">
                        <input id="taskName" name="taskName" type="text" value={data.taskName} onChange={this.onChange} />
                        <span className="e-float-line"/>
                        <label className="e-float-text e-label-top">Task Name</label>
                    </div>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                <DropDownListComponent id="priority" value={data.priority} dataSource={this.priorityData}
                        fields={{text: 'priority', value: 'priority' }} placeholder="Priority"
                        popupHeight='300px' floatLabelType='Always'/>
                </div>
                <div className="form-group col-md-6">
                   <NumericTextBoxComponent id="progress" format='n' value={data.progress}
                    placeholder="Progress" floatLabelType='Always'/>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                        <DatePickerComponent value={data.startDate} floatLabelType='Always' placeholder="Start Date"/>
                        <span className="e-float-line"/>
                    </div>
                </div>
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                    <DatePickerComponent value={data.endDate} floatLabelType='Always' placeholder="End Date" />
                        <span className="e-float-line"/>
                    </div>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                    <CheckBoxComponent checked={data.approved} label='Approved'/>
                        <span className="e-float-line"/>
                    </div>
                </div>
            </div>
        </div>);
    }
}
export interface IOrderModel {
    taskID?: number;
    taskName?: string;
    priority?: string;
    progress?: number;
    startDate?: Date;
    endDate?: Date;
    isAdd?: boolean;
    approved?: boolean;
}
import { setValue } from '@syncfusion/ej2-base';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
import { DialogFormTemplate } from './template';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Dialog',
            template: this.dialogTemplate.bind(this)
        };
    }
    dialogTemplate(props) {
        const obj = [props, this.treegrid];
        return (<DialogFormTemplate {...obj}/>);
    }
    actionComplete(args) {
        if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
            // Add Validation Rules
            const form = args.form;
            form.ej2_instances[0].addRules('progress', { max: 100 });
            if (args.requestType === 'beginEdit') {
                form.elements.namedItem('taskName').focus();
            }
        }
    }
    actionBegin(args) {
        if (args.requestType === 'save') {
            // cast string to integer value.
            const val = args.form
                .querySelector("#progress").value;
            setValue('data.progress', parseFloat(val), args);
        }
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions} ref={g => this.treegrid = g} actionBegin={this.actionBegin} actionComplete={this.actionComplete}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
import { DataUtil } from '@syncfusion/ej2-data';
import { CheckBoxComponent } from '@syncfusion/ej2-react-buttons';
import { DatePickerComponent } from '@syncfusion/ej2-react-calendars';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import { sampleData as orderData } from './datasource';
export class DialogFormTemplate extends React.Component {
    constructor(props) {
        super(props);
        this.priorityData = DataUtil.distinct(orderData, 'priority', true);
        this.state = Object.assign({}, props[0]);
    }
    onChange(args) {
        this.setState({ [args.target.name]: args.target.value });
    }
    render() {
        this.onChange = this.onChange.bind(this);
        const data = this.state;
        return (<div>
            <div className="form-row">
                <div className="form-group col-md-6">
                <div className="e-float-input e-control-wrapper">
                        <input id="taskID" name="taskID" disabled={!data.isAdd} type="text" value={data.taskID} onChange={this.onChange}/>
                        <span className="e-float-line"/>
                        <label className="e-float-text e-label-top">Task ID</label>
                    </div>

                </div>
                <div className="form-group col-md-6">
                <div className="e-float-input e-control-wrapper">
                        <input id="taskName" name="taskName" type="text" value={data.taskName} onChange={this.onChange}/>
                        <span className="e-float-line"/>
                        <label className="e-float-text e-label-top">Task Name</label>
                    </div>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                <DropDownListComponent id="priority" value={data.priority} dataSource={this.priorityData} fields={{ text: 'priority', value: 'priority' }} placeholder="Priority" popupHeight='300px' floatLabelType='Always'/>
                </div>
                <div className="form-group col-md-6">
                   <NumericTextBoxComponent id="progress" format='n' value={data.progress} placeholder="Progress" floatLabelType='Always'/>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                        <DatePickerComponent value={data.startDate} floatLabelType='Always' placeholder="Start Date"/>
                        <span className="e-float-line"/>
                    </div>
                </div>
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                    <DatePickerComponent value={data.endDate} floatLabelType='Always' placeholder="End Date"/>
                        <span className="e-float-line"/>
                    </div>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group col-md-6">
                    <div className="e-float-input e-control-wrapper">
                    <CheckBoxComponent checked={data.approved} label='Approved'/>
                        <span className="e-float-line"/>
                    </div>
                </div>
            </div>
        </div>);
    }
}

The template form editors should have name attribute.

Template Context

The template should be a React Component class. You can access the row information inside the Component class using props, you can bind the attribute or value based on this row information.

The following properties will be available at the time of template execution.

Property Name Usage
isAdd A Boolean property; it defines whether the current row should be a new record or not.

In the following code example, the OrderID textbox has been disabled by using the isAdd property.

// The disabled attributes will be added based on the isAdd property.
<input id="taskID" name="taskID" type="text" disabled={!data.isAdd} value={data.taskID} onChange={this.onChange} />

The following code example illustrates rendering the taskID textbox, when a new record is added.

Get value from editor

You can read, format, and update the current editor value in the actionBegin event at the time of setting requestType to save.

In the following code example, the progress value has been formatted and updated.

    public actionBegin (args: DialogEditEventArgs) {
        if (args.requestType === 'save') {
            // cast string to integer value.
            const val: string = ((args.form as HTMLFormElement)
                .querySelector("#progress") as HTMLInputElement).value;
            setValue('data.progress', parseFloat(val), args);
        }
    }

Set focus to editor

By default, the first input element in the dialog will be focused while opening the dialog. If the first input element is in disabled or hidden state, focus the valid input element in the actionComplete event based on requestType as beginEdit.

    public actionComplete(args: DialogEditEventArgs) {
       if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
            const form: HTMLFormElement = args.form as HTMLFormElement;
            if (args.requestType === 'beginEdit') {
                (form.elements.namedItem('taskName') as HTMLInputElement).focus();
            }
       }
    }

Adding validation rules for custom editors

If you have used additional fields that are not present in the column model, then add the validation rules to them in the actionComplete event.

    public actionComplete(args: DialogEditEventArgs) {
       if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
           // Add Validation Rules
            const form: HTMLFormElement = args.form as HTMLFormElement;
            form.ej2_instances[0].addRules('progress', {max: 100});
       }
    }

Adding row position

The TreeGrid control provides the support to add the new row in the top, bottom, above selected row, below selected row and child position of tree grid content using editSettings.newRowPosition property. By default, a new row will be added at the top of the treegrid.

The following examples shows how to set new row position as Child in tree grid.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell',
        newRowPosition: 'Child'
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell',
            newRowPosition: 'Child'
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Command column

The command column provides an option to add CRUD action buttons in a column. This can be defined by the column.commands property.

The available built-in command buttons are:

Command Button Actions
Edit Edit the current row.
Delete Delete the current row.
Save Update the edited row.
Cancel Cancel the edited state.
Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { CommandModel } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { CommandColumn, Edit, EditSettingsModel } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public commands: CommandModel[] = [
        {
            buttonOption: { cssClass: 'e-flat', iconCss: 'e-edit e-icons' },
            type: 'Edit',
        },
        {
            buttonOption: { cssClass: 'e-flat', iconCss: 'e-delete e-icons' },
            type: 'Delete'
        },
        {
            buttonOption: { cssClass: 'e-flat', iconCss: 'e-update e-icons' },
            type: 'Save'
        },
        {
            buttonOption: { cssClass: 'e-flat', iconCss: 'e-cancel-icon e-icons' },
            type: 'Cancel'
        }
    ];
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Row'
    };
    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
              <ColumnDirective headerText='Manage Records' width='130' commands= {this.commands}/>
            </ColumnsDirective>
            <Inject services={[Edit,CommandColumn]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { CommandColumn, Edit } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.commands = [
            {
                buttonOption: { cssClass: 'e-flat', iconCss: 'e-edit e-icons' },
                type: 'Edit',
            },
            {
                buttonOption: { cssClass: 'e-flat', iconCss: 'e-delete e-icons' },
                type: 'Delete'
            },
            {
                buttonOption: { cssClass: 'e-flat', iconCss: 'e-update e-icons' },
                type: 'Save'
            },
            {
                buttonOption: { cssClass: 'e-flat', iconCss: 'e-cancel-icon e-icons' },
                type: 'Cancel'
            }
        ];
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Row'
        };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
              <ColumnDirective headerText='Manage Records' width='130' commands={this.commands}/>
            </ColumnsDirective>
            <Inject services={[Edit, CommandColumn]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Custom command

The custom command buttons can be added in a column by using the column.commands property and the action for the custom buttons can be defined in the buttonOption.click event.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { closest } from '@syncfusion/ej2-base';
import { Column, CommandModel, Row } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { CommandColumn, Edit, EditSettingsModel, TreeGrid } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = { allowEditing: true, allowDeleting: true };
    public commands: CommandModel[] = [
      {
        buttonOption: {
          click: this.onClick.bind(this),
          content: 'Details', cssClass: 'e-flat'
        }
      }
    ];
    public treegrid: TreeGrid | null;
  
    public onClick(args: Event): void  {
      if (this.treegrid) {
        const rowObj: Row<Column> =
          this.treegrid.grid.getRowObjectFromUID(closest(args.target as Element, '.e-row')
          .getAttribute('data-uid') as string);
        const rowData: object = rowObj.data as object;
        alert(JSON.stringify(rowData));
      }
    }

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} ref={g=> this.treegrid = g}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
              <ColumnDirective headerText='Commands' width='120' commands= {this.commands}/>
            </ColumnsDirective>
            <Inject services={[Edit,CommandColumn]}/>
        </TreeGridComponent>
    }
}
import { closest } from '@syncfusion/ej2-base';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { CommandColumn, Edit } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = { allowEditing: true, allowDeleting: true };
        this.commands = [
            {
                buttonOption: {
                    click: this.onClick.bind(this),
                    content: 'Details', cssClass: 'e-flat'
                }
            }
        ];
    }
    onClick(args) {
        if (this.treegrid) {
            const rowObj = this.treegrid.grid.getRowObjectFromUID(closest(args.target, '.e-row')
                .getAttribute('data-uid'));
            const rowData = rowObj.data;
            alert(JSON.stringify(rowData));
        }
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} ref={g => this.treegrid = g}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
              <ColumnDirective headerText='Commands' width='120' commands={this.commands}/>
            </ColumnsDirective>
            <Inject services={[Edit, CommandColumn]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Confirmation messages

Delete confirmation

The delete confirm dialog can be shown when deleting a record by defining the showDeleteConfirmDialog as true

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell',
        showDeleteConfirmDialog: true
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit' />
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell',
            showDeleteConfirmDialog: true
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='130' format='yMd' textAlign='Right' type='date' editType='datepickeredit'/>
              <ColumnDirective field='duration' headerText='Duration' width='80' textAlign='Right'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

The showDeleteConfirmDialog supports all type of edit modes.

Column validation

Column validation allows you to validate the edited or added row data and it display errors for invalid fields before saving data. TreeGrid uses Form Validator component for column validation. You can set validation rules by defining the columns.validationRules.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { IEditCell } from '@syncfusion/ej2-grids';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell',
        showDeleteConfirmDialog: true
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public format: any = {type:'dateTime', format:'M/d/y hh:mm a'};

    public datetimeParams: IEditCell = { params: { format: 'M/d/y hh:mm a' } };
    public numericParams: IEditCell = { params: { format: 'n' } };

    public taskIDRules: object = { required: true, number: true };
    public progressRules: object = { number: true, min: 0 };
    public startDateRules: object = { date: true };
    public priorityRules: object = { required: true };
    public taskNameRules: object = { required: true };

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true} validationRules={this.taskIDRules}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' validationRules={this.taskNameRules}/>
              <ColumnDirective field='startDate' headerText='Start Date' width='150' textAlign='Right' edit={this.datetimeParams}
               editType='datetimepickeredit' format={this.format} validationRules={this.startDateRules} />
              <ColumnDirective field='approved' headerText='Approved' width='110' textAlign='Right' editType='booleanedit' type='boolean' displayAsCheckBox={true} />
              <ColumnDirective field='progress' headerText='Progress' textAlign='Right' width='120' editType='numericedit' edit={this.numericParams} validationRules={this.progressRules} />
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' validationRules={this.priorityRules} />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell',
            showDeleteConfirmDialog: true
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
        this.format = { type: 'dateTime', format: 'M/d/y hh:mm a' };
        this.datetimeParams = { params: { format: 'M/d/y hh:mm a' } };
        this.numericParams = { params: { format: 'n' } };
        this.taskIDRules = { required: true, number: true };
        this.progressRules = { number: true, min: 0 };
        this.startDateRules = { date: true };
        this.priorityRules = { required: true };
        this.taskNameRules = { required: true };
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true} validationRules={this.taskIDRules}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180' validationRules={this.taskNameRules}/>
              <ColumnDirective field='startDate' headerText='Start Date' width='150' textAlign='Right' edit={this.datetimeParams} editType='datetimepickeredit' format={this.format} validationRules={this.startDateRules}/>
              <ColumnDirective field='approved' headerText='Approved' width='110' textAlign='Right' editType='booleanedit' type='boolean' displayAsCheckBox={true}/>
              <ColumnDirective field='progress' headerText='Progress' textAlign='Right' width='120' editType='numericedit' edit={this.numericParams} validationRules={this.progressRules}/>
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' validationRules={this.priorityRules}/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Custom validation

You can define your own custom validation rules for the specific columns by using Form Validator custom rules.

In the below demo, custom validation applied for Priority column.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { getValue } from '@syncfusion/ej2-base';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell'
    };
    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];
    public priorityRules: object = {
        minLength: [this.customFn, 'Value should be within 8 letters'],
        required: true
    };
    public customFn(args: { [key: string]: string }) : boolean {
        return getValue('value', args) <= 8;
    };


    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' textAlign='Right' editType='datepickeredit' format='yMd' type='date' />
              <ColumnDirective field='duration' headerText='Duration' width='110' validationRules={this.priorityRules} />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell'
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
        this.priorityRules = {
            minLength: [this.customFn, 'Value should be within 8 letters'],
            required: true
        };
    }
    customFn(args) {
        return getValue('value', args) <= 8;
    }
    ;
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' textAlign='Right' editType='datepickeredit' format='yMd' type='date'/>
              <ColumnDirective field='duration' headerText='Duration' width='110' validationRules={this.priorityRules}/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Default column values on add new

The treegrid provides an option to set the default value for the columns when adding a new record in it. To set a default value for the particular column by defining the columns.defaultValue.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell'
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' textAlign='Right' editType='datepickeredit' format='yMd' type='date' />
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' defaultValue='Normal' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell'
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' textAlign='Right' editType='datepickeredit' format='yMd' type='date'/>
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' defaultValue='Normal'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Disable editing for particular column

You can disable editing for particular columns by using the columns.allowEditing.

In the following demo, editing is disabled for the Start Date column.

Source
Preview
App.tsx
App.css.jsx
App.jsx
index.jsx
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, EditSettingsModel, Toolbar, ToolbarItems } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';

export default class App extends React.Component<{}, {}>{
    public editOptions: EditSettingsModel = {
        allowAdding: true,
        allowDeleting: true,
        allowEditing: true,
        mode: 'Cell'
    };

    public toolbarOptions: ToolbarItems[] = ['Add', 'Delete', 'Update', 'Cancel'];

    public render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270'
         editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' allowEditing={false} textAlign='Right' editType='datepickeredit' format='yMd' type='date' />
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit' />
            </ColumnsDirective>
            <Inject services={[Edit,Toolbar]}/>
        </TreeGridComponent>
    }
}
import { ColumnDirective, ColumnsDirective, Inject, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { Edit, Toolbar } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import './App.css';
import { sampleData } from './datasource';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.editOptions = {
            allowAdding: true,
            allowDeleting: true,
            allowEditing: true,
            mode: 'Cell'
        };
        this.toolbarOptions = ['Add', 'Delete', 'Update', 'Cancel'];
    }
    render() {
        return <TreeGridComponent dataSource={sampleData} treeColumnIndex={1} childMapping='subtasks' height='270' editSettings={this.editOptions} toolbar={this.toolbarOptions}>
            <ColumnsDirective>
              <ColumnDirective field='taskID' headerText='Task ID' width='90' textAlign='Right' isPrimaryKey={true}/>
              <ColumnDirective field='taskName' headerText='Task Name' width='180'/>
              <ColumnDirective field='startDate' headerText='Start Date' width='90' allowEditing={false} textAlign='Right' editType='datepickeredit' format='yMd' type='date'/>
              <ColumnDirective field='priority' headerText='Priority' width='110' editType='dropdownedit'/>
            </ColumnsDirective>
            <Inject services={[Edit, Toolbar]}/>
        </TreeGridComponent>;
    }
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

Troubleshoot: Editing works only for first row

The Editing functionalities can be performed based upon the primary key value of the selected row. If column.primaryKey is not defined in the treegrid, then edit or delete action take places the first row.