DataGrid - TreeGrid
The <DataGrid /> offers support for hierarchical data - configure a treeColumn and make your dataSource items have a nodes array with child records.
The treeColumn specifies which column will render the tree collapse/expand/loading icons (the icon can be further configured via renderNodeTool prop).
When using <DataGrid /> as a tree, we refer to rows as nodes.
Expanded nodes are managed via the expandedNodes prop (this prop is controlled, see defaultExpandedNodes for uncontrolled version). The value of this prop should be an object - the keys in this object are the ids of the expanded nodes, while the value for each key should be true.
Nested nodes should have an id but it only needs to be unique at their nesting level. The <DataGrid /> will assign a unique id (see idProperty) to all nodes based on the path from the root node to the respective node. This id value is built by joining all the parent ids using the / character (as defined by nodePathSeparator prop). So, for example, expandedNodes could look like this for a grid: expandedNodes={ 1: true, 3: true, '3/1': true', '3/2/1': true }.
The code snippet below shows a basic example of the tree functionality
Using the tree functionality in the <DataGrid /> is not compatible with grouping rows.
Also, because of the hierarchical nature of the dataSource, setItemAt (and friends - setItemPropertyAt and setItemPropertyForId), cannot be used for the time being with the tree functionality.
For now, the tree functionality is not integrated with row selection - meaning that it does not yet support reccursive selection for nodes.
The tree functionality is compatible with sorting/filtering/pagination/live pagination features of the <DataGrid />.
Maybe the most important aspect of understanding the tree functionality in the <DataGrid /> is understanding async and leaf nodes.
If a tree node has the nodes property defined (so if nodes !== undefined) it is not a leaf node.
A node is a leaf if it has nodes === undefined (the nodes property name is configurable via nodesProperty).
If the nodes property of a tree node is an array, the node is a parent node (even if nodes.length === 0) and also a synchronous node.
A node is async if the nodes property is equal to null. In this case, when the user tries to expand the async node, the <DataGrid /> calls the loadNode({ node, nodeProps }) function prop to load the node children. Alternatively, you could specify loadNodeOnce({ node, nodeProps }) to have the grid load the node children and cache them for future re-use.
Both loadNode({ node, nodeProps }) and loadNodeOnce({ node, nodeProps }) should either return an array (or undefined) or a Promise that resolves to an array (or undefined).
The condition of a node to be async or leaf can be overriden by the isNodeAsync({ node, nodeProps }) and isNodeLeaf({ node, nodeProps }) props respectively.
The depth at which the tree nodes are rendered can be configured via the treeNestingSize.
When a node is expanded or collapsed, the onExpandedNodesChange({ expandedNodes }) function prop is called. Before this function being called, you can cancel the expand by returning false from onNodeExpand or from onNodeExpandChange (called in this order). Cancelling a node collapse can be done by returning false from onNodeCollapse or from onNodeExpandChange (called in this order).
When using the controlled expandedNodes, don't forget to update the prop in response to onExpandedNodesChange being called.