Create a Hierarchical Table of Record Data

The lightning-tree-grid component displays rows of data that can be expanded to reveal child records.

The lightning-tree-grid component is built on lightning-datatable and supports a subset of its features. See Display Record Data in a Table for a comparison of features offered by each component.

Display Records and Child Records 

Let’s create a table that displays accounts with associated cases. Each row-level action enables you to edit the account or case record using the navigation service.

A data table displaying accounts and associated new cases

Let’s get our data using Apex. In this example, CaseController.cls contains a SOQL statement that returns the account names and all associated cases with a status of New.

1//CaseController.cls
2public with sharing class CaseController {
3    @AuraEnabled(cacheable=true)
4    public static list<Account> getNewCasesForAccounts(){
5        return [SELECT Name, (
6                SELECT Id, CaseNumber, Status FROM Cases WHERE toLabel(Status) = 'New')
7                FROM Account WHERE Id IN (SELECT AccountId FROM Case)];
8    }
9}

In your JavaScript file myTreeGrid.js, use @wire to call the Apex method. Define rows that contain child items using the _children key. Rows with child items display with a chevron button that toggles the child items.

1//myTreeGrid.js
2import { LightningElement, wire, track } from "lwc";
3import { NavigationMixin } from "lightning/navigation";
4
5import getNewCases from "@salesforce/apex/CaseController.getNewCasesForAccounts";
6
7const actions = [{ label: "Edit", name: "edit_record" }];
8
9const COLS = [
10  {
11    fieldName: "Name",
12    label: "Account Name",
13  },
14  {
15    fieldName: "CaseNumber",
16    label: "New Cases",
17    cellAttributes: {
18      iconName: { fieldName: "iconName" },
19    },
20  },
21  {
22    type: "action",
23    label: "Edit Record",
24    typeAttributes: {
25      rowActions: actions,
26      menuAlignment: "right",
27    },
28  },
29];
30
31export default class MyTreeGrid extends NavigationMixin(LightningElement) {
32  @track myData = [];
33  columns = COLS;
34  error;
35
36  @wire(getNewCases)
37  wiredCases({ error, data }) {
38    if (error) {
39      // Handle error
40      this.error = error;
41    } else if (data) {
42      // Process record data
43      var strData = JSON.parse(JSON.stringify(data));
44
45      strData.map((row, index) => {
46        if (row["Cases"]) {
47          row._children = row["Cases"]; //define rows with children
48          delete row.Cases;
49
50          let iconKey = "iconName";
51          row[iconKey] = "standard:case";
52        }
53      });
54      this.myData = strData;
55    }
56  }
57
58  handleRowAction(event) {
59    const action = event.detail.action;
60    const row = event.detail.row;
61    switch (action.name) {
62      case "edit_record":
63        this[NavigationMixin.Navigate]({
64          type: "standard__objectPage",
65          attributes: {
66            objectApiName: "Case",
67            actionName: "edit",
68            recordId: row.Id,
69          },
70        });
71        break;
72    }
73  }
74}

Use the lightning-tree-grid Component 

After you define the rows and columns, you can display your data using the lightning-tree-grid component.

1<!--myTreeGrid.html-->
2<template>
3  <lightning-tree-grid
4    columns={columns}
5    data={myData}
6    key-field="Id"
7    onrowaction={handleRowAction}
8  >
9  </lightning-tree-grid>
10</template>

See Also

Release Preview

This release is in preview. Features described here don't become generally available until the latest general availability date that Salesforce announces for this release. Before then, and where features are noted as beta, pilot, or developer preview, we can't guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features.