Types of Hierarchical Data
At a high level, we classify hierarchical data grids into two types:
- Grids that have a single set of top level columns. We call these Grouped Data Grids.
- Grids that have multiple sets of inner level columns. We call these Nested Data Grids.
Grouped Data Grids
Lets take a quick look at what a grouped datagrid looks like.
Using pre grouped data
For grouping to work, we need data in a hierarchical format, with a field on the parent that returns an array of children.
e.g.
SampleData.networkData = [
{
id: "3190", ...
items: [
{
id: "31469", ...
},
{
id: "31470", ...
items: [
{
id: "3144141", ...
items: [],
},
{
id: "3144142", ...
items: [],
},
{
id: "3144143", ...
items: [],
},
{
id: "3144144", ...
items: [],
},
],
},
{
id: "31471", ...
items: [],
},
],
},
{
id: "3191", ...
items: [],
},
];
This example demonstrates a few features of hierarchical grids:
- enableSelectionCascade & enableSelectionBubble - These two features allow you to select a parent and all its children, or select a child and all its parents if all the children are selected.
- enableHierarchy - This feature allows you to expand and collapse the rows, and indent the children.
- expandAll - This method expands all the rows in the grid. This ensures the grid opens with all the rows expanded.
- The Expand Collapse buttons in the toolbar - These buttons allow you to expand and collapse the rows at each level, or all the rows at once.
- The quickfind feature continues to work even when the rows are grouped.
- In future examples, we will also show how the grid's filters, footers, and other features integrate with the hierarchy.
Using the Grid's grouping API
We can also use the grid's grouping API to group the data. This is useful when you want to group the data on the fly, or when you have flat data that you want to group on the client instead of the server.
There is a LOT going on here, so please bear with us as we try to break this down.
First, you noticed that we are importing data using the FlexiciousMockGenerator
class. This is a class that we use to generate mock data for our examples. This is returning an array of about 10,000 line items. Each line item has a Invoice, that maps to a customer, that has an address. We are using the address object's Country, State, and City to group the data.
Second, we added two behaviors to the grid. The first is the createFilterBehavior
which allows you to filter the data. The second is the createGroupingBehavior
which allows you to group the data. This is because we dont want to includ all the grouping modules unless you need them. This helps keep the bundle size down for our customers who dont need grouping.
Third, we setup a useEffect hook to initially group the data. In most cases, you will have dependencies to this useEffect hook that will only trigger AFTER the raw data is loaded. In our case, we are using mock data, so we dont have any dependencies. We also setup a second useEffect hook to expand all the groups after the data is grouped, which is a common requirement, but not always needed.
Fourth, we setup a onGroupingFieldsChanged
event handler on the grid. This event handler is called whenever the grouping changes. This is where you would typically update your data provider with the new grouped data. In our case, we are using the getGroupedDataProvider
method on the api
object to get the grouped data. We are also saving the grouping fields in state, so that we can use them in the second useEffect hook.
Finally, we setup the columns. We have a column that is marked as enableHierarchy
which is the column that will display the group name. We also marked enableGroupingDropzone
as false to keep this example simple. This is because we are using the groupBy
method to group the data, and we dont want to allow the user to drag and drop columns to group the data, but you can enable this if you want to.
So basically the flow here is,
- We load the raw data
- We set the grouping fields by calling the
groupBy
method - In response, the grid dispatches the
onGroupingFieldsChanged
event - We respond to this event by calling the
getGroupedDataProvider
method on theapi
object to get the grouped data - The grid gives us the grouped data, and we update the data provider on the grid.
We recommend you use the groupBy
method to group your data. This helps you in two ways
- It will automatically assign a globally unique identifier to each row, which is required for grouping to work.
- It will save you from having to write a lot of code to group your data :-)
- With the original data intact, you can always clear the grouping by calling the
clearGroupBy
method.
There is a much more detailed version of this example here: Grouping This shows you how to integrate filtering, multiple vs single grouping columns, allowing the user the perform drag and drop grouping, and more.
Nested Data Grids
Unlike Grouped DataGrids, Nested Data Grids support multiple levels of columns. This is useful when you have related, yet distinct entities that you want to display in a single grid. For example, you may have a list of organizations, and each organization has a list of projects, and each project has a list of invoices, and each invoice has a list of line items. You can display all of this data in a single grid, and the user can expand and collapse the rows to see the related data.
Let's take a look at an example.
Phew! That's a lot of code, but please dont let it scare you! Close to 90% of the code above is just defining the columns and styling the grid.
When you define inner level columns, its always nice to define cell and row styles that visually separate the levels. This also gives you the opportunity to remove the vertical lines between the cells, which can be distracting.
There is another little gem in this code, the enableFloatingHeaderRows property. This property enables the anchor parent row to be displayed as a floating header row. This is a great way to keep the parent row visible as you scroll down the grid so users dont loose context of where they are in the hierarchy.
There is a much more advanced example of this in the Advanced Hierarchy Example