This is part of the Ext JS to React blog series. You can review the code from this article on the Ext JS to React Git repo.
Not all data can be presented in a simple grid since not all data is flat. Take, for example, the file system on your computer. Folders can hold files as well as other nested folders, allowing your data to be organized in a hierarchical (or tree) shape. In Ext JS, a tree panel is effectively a grid with a column that displays the names of the files and folders along with an icon used to toggle the collapse state of each parent node. With ag-Grid, the same is true. We’ve been using ag-Grid as a pre-built solution to display grids and we’ll continue to use it to display a tree.
Note: While many features from ag-Grid are free, displaying data in a tree with ag-Grid is part of their enterprise pricing model. For this demonstration, you can sign up for a trial enterprise license.
Note: While not a requirement for React, this article’s code examples assume you’re starting with a starter app generated by create-react-app.
ag-Grid setup
First, install ag-Grid including the files we’ll use to theme the grid:
npm install --save ag-grid npm install --save ag-grid-react npm install --save ag-grid-enterprise
If you’re using React 16+ you may also need to install react-dom-factories
:
npm install --save react-dom-factories
Sample Tree Data
Below is the data we’ll use for our two tree examples:
const data = [ { orgHierarchy: ['Erica Rogers'], jobTitle: 'CEO', employmentType: 'Permanent', email: 'erica.rogers@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett'], jobTitle: 'Exec. Vice President', employmentType: 'Permanent', email: 'malcolm.barrett@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Esther Baker'], jobTitle: 'Director of Operations', employmentType: 'Permanent', email: 'esther.baker@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Esther Baker', 'Brittany Hanson'], jobTitle: 'Fleet Coordinator', employmentType: 'Permanent', email: 'brittany.hanson@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Esther Baker', 'Brittany Hanson', 'Leah Flowers'], jobTitle: 'Parts Technician', employmentType: 'Contract', email: 'leah.flowers@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Esther Baker', 'Brittany Hanson', 'Tammy Sutton'], jobTitle: 'Service Technician', employmentType: 'Contract', email: 'tammy.sutton@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Esther Baker', 'Derek Paul'], jobTitle: 'Inventory Control', employmentType: 'Permanent', email: 'derek.paul@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Francis Strickland'], jobTitle: 'VP Sales', employmentType: 'Permanent', email: 'francis.strickland@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Francis Strickland', 'Morris Hanson'], jobTitle: 'Sales Manager', employmentType: 'Permanent', email: 'morris.hanson@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Francis Strickland', 'Todd Tyler'], jobTitle: 'Sales Executive', employmentType: 'Contract', email: 'todd.tyler@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Francis Strickland', 'Bennie Wise'], jobTitle: 'Sales Executive', employmentType: 'Contract', email: 'bennie.wise@acme.com' }, { orgHierarchy: ['Erica Rogers', 'Malcolm Barrett', 'Francis Strickland', 'Joel Cooper'], jobTitle: 'Sales Executive', employmentType: 'Permanent', email: 'joel.cooper@acme.com' } ];
The data structure is flat. The orgHierarchy
array is what is used to build the parent child relationship. Effectively, that array is the hierarchy. ag-Grid loops through the array, finds the matching node as a parent and adds data to that parent. The other fields in the data are for the last entry in the orgHierarchy
array.
ag-Grid Tree Configuration
With Ext JS, the TreeStore
does most of the data handling. It creates all the records and nests them in childNodes
array. This is almost exactly how JavaScript manages the DOM. Child nodes are in an element’s childNodes
property. With ag-Grid, the data is flat, but is given an array to build the hierarchy for you automatically. Below is an example of the Tree component:
import React, { Component } from 'react'; import { AgGridReact } from 'ag-grid-react'; import 'ag-grid/dist/styles/ag-grid.css'; import 'ag-grid/dist/styles/ag-theme-material.css'; import 'ag-grid-enterprise'; import {LicenseManager} from "ag-grid-enterprise/main"; // The tree view from ag-Grid requires an enterprise license and a product key // Pricing: https://www.ag-grid.com/license-pricing.php // Trial: https://www.ag-grid.com/start-trial.php LicenseManager.setLicenseKey("your license key"); class App extends Component { columns = [ { field: 'jobTitle' }, { field: 'employmentType' } ] getDataPath = (data) => { return data.orgHierarchy; } autoGroupColumnDef = { headerName: 'Organization Hierarchy', width: 300, cellRendererParams: { suppressCount: true } } render () { return ( <div className="ag-theme-material"> <AgGridReact containerStyle={{height: '400px'}} columnDefs={this.columns} rowData={data} treeData={true} getDataPath={this.getDataPath} autoGroupColumnDef={this.autoGroupColumnDef} /> </div> ); } } export default App;
This looks very similar to the grids we’ve configured before, but there are three key configs:
treeData
: This is pretty self documenting, but it tells the grid that it will be working with data to display a treegetDataPath
: A function that will return the array that will be used to build the hierarchical dataautoGroupColumnDef
: A column definition (like what we have in the columns array) that will be added to display the tree UI bits like the expand / collapse icon. This column can be thought of as the “tree column”.
You can review the sample code on the Git repo.
ag-Grid Tree Features
As we’ve seen in the Features and Plugins article, ag-Grid’s grid component offers advanced features above and beyond the basic implementation. Since the ag-Grid tree is just a grid, the same features we’ve seen used with the grid can be used by the tree:
import React, { Component } from 'react'; import { AgGridReact } from 'ag-grid-react'; import 'ag-grid/dist/styles/ag-grid.css'; import 'ag-grid/dist/styles/ag-theme-material.css'; import 'ag-grid-enterprise'; import {LicenseManager} from "ag-grid-enterprise/main"; // The tree view from ag-Grid requires an enterprise license and a product key // Pricing: https://www.ag-grid.com/license-pricing.php // Trial: https://www.ag-grid.com/start-trial.php LicenseManager.setLicenseKey("your license key"); class App extends Component { columns = [ { field: 'jobTitle', editable: true }, { field: 'employmentType' }, { field: 'email', cellRenderer: params => { return `<a href="mailto:${params.value}">${params.value}</a>`; } } ] getDataPath = (data) => { return data.orgHierarchy; } autoGroupColumnDef = { headerName: 'Organisation Hierarchy', width: 300, pinned: 'left', editable: true, cellRendererParams: { suppressCount: true } } render () { return ( <div className="ag-theme-material"> <AgGridReact containerStyle={{height: '400px', width: '700px'}} columnDefs={this.columns} rowData={data} treeData={true} getDataPath={this.getDataPath} autoGroupColumnDef={this.autoGroupColumnDef} enableGroupEdit={true} /> </div> ); } } export default App;
In this example, we enabled cell rendering, column locking, and cell editing. For cell rendering, there is a new “email” column that uses the cellRenderer
to return a clickable link. The first column showing the tree icons is also pinned to the left so you can scroll to see the other columns, yet always see who the data belongs to. To enable cell editing, we added editable
config to both the “job title” and the “tree” column. It will render the default text editor on double-click. To enable double-click editing, we had to prevent the tree from expanding the node on double-click using the enableGroupEdit
prop.
You can review the sample code on the Git repo.
Conclusion
Just as we used ag-Grid to create a grid matching Ext JS’s grid, we can use ag-Grid to match Ext JS’s tree as well. Once again, we see that the transition from Ext JS to React isn’t as scary as it first seems. The tree we used here isn’t free. However, ag-Grid’s enterprise pricing does allow single licenses and comes with a two-month free trial.
Have you used a grid or tree component in React that you love? As always, we’d like to hear from you! Please feel free to share any resources you’ve discovered for tabular / hierarchical data using the comments below!
Seth Lemmons
Related Posts
-
Ext JS to React: Migration to Open Source
Worried about Migrating from Ext JS? Modus has the Answers Idera’s acquisition of Sencha has…
-
Ext JS to React: FAQ
This is part of the Ext JS to React blog series. React is Facebook's breakout…