Data Binding

The TreeView enables you to work with various types of data.

Basics

To bind the TreeView to data:

  1. Add children items to an item with an items field.
  2. Configure the data property.
const tree = [{
    text: 'Furniture', expanded: true, items: [
        { text: 'Tables & Chairs' }, { text: 'Sofas' }, { text: 'Occasional Furniture' }]
}, {
    text: 'Decor', expanded: true, items: [
        { text: 'Bed Linen' }, { text: 'Curtains & Blinds' }, { text: 'Carpets' }]
}];

class App extends React.Component {
    render() {
        return <TreeView data={tree} />;
    }
}

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

Item Fields

By default, the TreeView provides the following fields for its items:

  • text—The string representation of the item.
  • items—The children of the item.
  • expanded—If set to true, expands the item.
  • selected—If set to true, selects the item.
  • disabled—If set to true, disables the item.
  • checked—If set to true, checks the item.
  • checkIndeterminate—If set to true, applies an indeterminate check to the item.
  • hasChildren—If set to true, notifies the TreeView that the item has children even if they are not initially passed. Used for implementing the load-on-demand feature.

Apart form items, you can replace each of the default TreeView fields with custom ones. To include your own fields, set the corresponding TreeView property to the name of the custom field. The TreeView also supports the nesting of its item fields.

const tree = [{
    data: { text: 'Furniture' }, opened: true, items: [
        { data: { text: 'Tables & Chairs' } },
        { data: { text: 'Sofas' } },
        { data: { text: 'Occasional Furniture' } }]
}, {
    data: { text: 'Decor' }, opened: true, items: [
        { data: { text: 'Bed Linen' } },
        { data: { text: 'Curtains & Blinds' } },
        { data: { text: 'Carpets' } }]
}];

class App extends React.Component {
    render() {
        return (
            <TreeView
                data={tree} textField="data.text"
                expandIcons={true} expandField="opened" onExpandChange={this.onExpandChange}
            />
        );
    }
    onExpandChange = (event) => {
        event.item.opened = !event.item.opened;
        this.forceUpdate();
    }
}

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

Loading Data on Demand

The following example demonstrates how to fetch remote data and bind the TreeView to it.

To implement the load-on-demand feature:

  1. Set the hasChildren field of the root items.
  2. Provide their children afterwards.
const baseUrl = 'https://odatasampleservices.azurewebsites.net/V4/Northwind/Northwind.svc/Categories';
const requestInit = { method: 'GET', accept: 'application/json', headers: [] };

class App extends React.Component {
    state = { data: [] };

    render() {
        return <TreeView data={this.state.data} expandIcons={true} onExpandChange={this.onExpandChange} />;
    }

    componentDidMount() {
        fetch(baseUrl, requestInit).then(response => response.json())
            .then(json => {
                const data = json.value.map(({ CategoryID, CategoryName }) => {
                    return { text: CategoryName, id: CategoryID, hasChildren: true }
                });

                this.setState({ data });
            });
    }

    onExpandChange = (event) => {
        const categoryIndex = Number(event.itemHierarchicalIndex);
        const { data, category } = this.copyDataAndCategory(categoryIndex);
        category.expanded = !category.expanded;

        this.setState({ data });

        !category.items && this.loadProducts(categoryIndex, category.id);
    }

    loadProducts(categoryIndex, categoryId) {
        fetch(`${baseUrl}(${categoryId})/Products`, requestInit).then(response => response.json())
            .then(json => {
                const { data, category } = this.copyDataAndCategory(categoryIndex);
                category.items = json.value.map(({ ProductName }) => {
                    return { text: ProductName }
                });

                this.setState({ data });
            });
    }

    copyDataAndCategory(categoryIndex) {
        const data = this.state.data.slice();
        const category = data[categoryIndex] = { ...data[categoryIndex] };

        return { data, category };
    }
}

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