Editing Basics

You can create, update, and delete the data records of the TreeList.

Getting Started

  1. Set the editField property of the TreeList—editField will indicate the editable data items and is part of the temporary data items that are used during editing. For the data items in the edit mode, set the edit state in their editField. In the following example, the id of the edited item is stored in the application state.

    <TreeList
        editField="inEdit"
    dataItem.inEdit = true;
  2. Create a new data tree which has the edit state of each data item by using the mapTree function.

    <TreeList
        editField="inEdit"
        data={
            mapTree(data, subItemsField, item =>
                extendDataItem(item, subItemsField, {
                    inEdit: item.id === this.state.editId
                })
            )
        }
  3. Set the editCell property per column. The built-in editor components are the TreeListTextEditor, TreeListNumericEditor, TreeListDateEditor, and TreeListBooleanEditor. The usage of each component for each column depends on the type of the edited data.

    <TreeList
        columns={[
            { field: 'name', editCell: TreeListTextEditor, ... },
            { field: 'position', editCell: TreeListTextEditor, ... },
            { field: 'hireDate', editCell: TreeListDateEditor, ... },
            { field: 'timeInPosition', editCell: TreeListNumericEditor, ... },
            { field: 'fullTime', editCell: TreeListBooleanEditor, ... }
        ]}
  4. Define a function for the onItemChange event which will handle the data changes during editing. Inside the event, all relevant data, such as the edited data item, the newly entered value, or the edited field will be available as onItemChange parameters.

    <TreeList onItemChange={this.onItemChange}>
    onItemChange = (event) => {
        this.setState({
            data: mapTree(
                this.state.data,
                subItemsField,
                item => item.id === event.dataItem.id ?
                    extendDataItem(item, subItemsField, { [event.field]: event.value }) : item
            )
        });
    }

The following example demonstrates how to set the TreeList in edit mode.

import React from 'react';
import ReactDOM from 'react-dom';
import {
    TreeList, TreeListToolbar, mapTree, extendDataItem,
    TreeListTextEditor, TreeListNumericEditor, TreeListDateEditor, TreeListBooleanEditor
} from '@progress/kendo-react-treelist';
import employees from './data';

const subItemsField = 'employees';
const expandField = 'expanded';
const editField = 'inEdit';
const columns = [
    { field: 'name', title: 'Name', width: 280, editCell: TreeListTextEditor, expandable: true },
    { field: 'position', title: 'Position', width: 260, editCell: TreeListTextEditor },
    { field: 'hireDate', title: 'Hire Date', format: '{0:d}', width: 170, editCell: TreeListDateEditor },
    { field: 'timeInPosition', title: 'Year(s) in Position', width: 170, editCell: TreeListNumericEditor },
    { field: 'fullTime', title: 'Full Time', width: 160, editCell: TreeListBooleanEditor }
];

class App extends React.Component {
    state = {
        data: employees.slice(),
        expanded: [1, 2, 32],
        editId: null
    }

    rowClick = (event) => {
        this.setState({
            editId: this.state.editId === event.dataItem.id ? null : event.dataItem.id
        });
    }

    onExpandChange = (event) => {
        this.setState({
            expanded: event.value ?
                this.state.expanded.filter(id => id !== event.dataItem.id) :
                [ ...this.state.expanded, event.dataItem.id ]
        });
    }

    onItemChange = (event) => {
        this.setState({
            data: mapTree(
                this.state.data,
                subItemsField,
                item => item.id === event.dataItem.id ?
                    extendDataItem(item, subItemsField, { [event.field]: event.value }) : item
            )
        });
    }

    closeEdit = (event) => {
        if (event.target === event.currentTarget) {
            this.setState({ editId: null });
        }
    }

    addRecord = () => {
        const newRecord = { id: new Date().getTime() };

        this.setState({
            data: [ newRecord, ...this.state.data ],
            editId: newRecord.id
        });
    }

    render() {
        const { data, expanded, editId } = this.state;

        return (
            <TreeList
                style={{ maxHeight: '510px', overflow: 'auto' }}
                data={
                    mapTree(data, subItemsField, item =>
                        extendDataItem(item, subItemsField, {
                            [expandField]: expanded.includes(item.id),
                            [editField]: item.id === editId
                        })
                    )
                }
                editField={editField}
                expandField={expandField}
                subItemsField={subItemsField}

                onRowClick={this.rowClick}
                onItemChange={this.onItemChange}
                onExpandChange={this.onExpandChange}
                columns={columns}
                toolbar={
                    <TreeListToolbar>
                        <div onClick={this.closeEdit}>
                            <button title="Add new" className="k-button k-primary" onClick={this.addRecord}>
                                Add new
                            </button>
                        </div>
                    </TreeListToolbar>
                }
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Edit Modes

 /