Generic Tree Grid Hierarchy LWC On Same sObject

Tree grid Hierarchy for records can improve user experience and gives more insight on parent child hierarchy at one place. Salesforce does give Account Hierarchy feature out of the box, but what if you want the similar functionality for Role Hierarchy or Case Hierarchy or any custom object hierarchy? Well, Now you can use this generic Lightning Web Component which allows you to have hierarchy view on single sObject records.

Code – LWC Generic Tree Grid Hierarchy Component

Lets create an apex method with name HierarchyController and a Lightning Web Component with name RoleHirarchyExplorer. We are going to demo how to display Role Hierarchy in LWC. You can modify this to have any kind of hierarchy with few change.

Apex Class – HierarchyController

There are two methods in this class. getAllHirarchy is a generic method which you can call to get the wrapper of parent and child map of any sObject which will be used by LWC to display the hierarchy.

getAllRoleHirarchy is a method to get the parent child map for UserRole sObject, similalry you can have methods to get other sObject hierarchy.

public class HierarchyController {
    //This method is for getting role hierarchy
    //you can create similar method for any other hierarchy
    @AuraEnabled
    public static hierarchyWrapper getAllRoleHirarchy(){
        List<UserRole> userRoleList = new List<UserRole>();
        userRoleList = [Select Id, Name, ParentRoleId from UserRole];
        return getAllHirarchy(userRoleList,'ParentRoleId');
    }
    
    //This is a generic method which returns a wrapper which holds map of parent and its child list
    @auraEnabled
    public static hierarchyWrapper getAllHirarchy(List<Sobject> recordList, String parentFieldApiName){
        Map<String,List<SObject>> mapofparentwithlistOfchild = new map<String, List<SObject>>();
        List<SObject> parentList = new List<SObject>();
        for(SObject record: recordList){
            if(record.get(parentFieldApiName) != null){
                if(mapofparentwithlistOfchild.containskey((String)record.get(parentFieldApiName))){
                    mapofparentwithlistOfchild.get((String)record.get(parentFieldApiName)).add(record);
                }else{
                    mapofparentwithlistOfchild.put((String)record.get(parentFieldApiName), new list<SObject>{record});
                }
            }else{
                parentList.add(record);
            }
        }
        hierarchyWrapper wrapper = new hierarchyWrapper();
        wrapper.superParentList = parentList;
        wrapper.parentMap = mapofparentwithlistOfchild;
        
        return wrapper;
    }
    
    public class hierarchyWrapper{
        @AuraEnabled public List<SObject> superParentList{get;set;}
        @AuraEnabled public Map<String,List<SObject>> parentMap{get;set;}
    }
}

RoleHirarchyExplorerLWC for Tree Grid Hierarchy

The lightning web component will have three files. They are html, js and meta xml file. You can create the component and copy the below code in respective file.

roleHirarchyExplorer.html

lightning-tree-grid component expects you to pass the columns and data to display. We have added lwc:if to make sure it renders only when data is available.

<template>
    <lightning-tree-grid lwc:if={hierarchyMap} columns={gridColumns} data={hierarchyMap}
        key-field="Id"></lightning-tree-grid>
</template>

roleHirarchyExplorer.js

As we are demonstrating Role Hierarchy, I have called the getAllRoleHirarchy apex method from HierarchyController class.

You can call your own method to fit your requirement. For example, if you are looking to get Case Hierarchy, You can create a method in HierarchyController class and pass the case list and parent field api name for case object to getAllHirarchy method by calling it. See below code

@AuraEnabled
public static hierarchyWrapper getAllAccountHirarchy(){
	List<Account> accountList = new List<Account>();
	accountList = [Select Id, Name, ParentId from Account];
	return getAllHirarchy(accountList,'ParentId');
}

Add above method in HierarchyController and call it in JS file.

Full JS Code

import { LightningElement, api } from 'lwc';
import getAllRoleHirarchy from '@salesforce/apex/HierarchyController.getAllRoleHirarchy';
const COLUMNS_DEFINITION_BASIC = [
    {
        type: 'text',
        fieldName: 'Name',
        label: 'Role Name',
    },
    {
        type: 'text',
        fieldName: 'Id',
        label: 'Role Id',
    },
];
export default class RoleHirarchyExplorer extends LightningElement {
    hierarchyMap;

    //pass your columns definition as per your requirement
    @api gridColumns = COLUMNS_DEFINITION_BASIC;

    //This is the field api name of field whose value will be put in parent field of child
    //for example UserRole, Id of the parent role will be the ParentRoleId field value of child role
    @api primaryKey = 'Id';

    connectedCallback() {
        //We ae making call of apex method which pass the sobjectlist and parent field api name
        //in getAllHirarchy generic method in HierarchyController
        //you can change the method as per your requirement
        getAllRoleHirarchy().then(result => {
            this.parseResult(result);
        }).catch(error => {
            console.log('error', error, JSON.stringify(error));
        });
    }

    parseResult(result) {
        this.hierarchyMap = [];
        result.superParentList.forEach(element => {
            this.hierarchyMap.push(this.findChildrenNode(element, result));
        });
        this.hierarchyMap = JSON.parse(JSON.stringify(this.hierarchyMap));
    }

    findChildrenNode(element, result) {
        for (var key in result.parentMap) {
            if (key == element[this.primaryKey]) {
                element["_children"] = result.parentMap[key];
                element["_children"].forEach(child => {
                    this.findChildrenNode(child, result);
                });
            }
        }
        return element;
    }
}

roleHirarchyExplorer.js-meta.xml

This file enables the component to be used with home, record and app page in lightning experience.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>57.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets> 
</LightningComponentBundle>

Demo – Tree Grid LWC Hierarchy on Same sObject

Do you need help?

Stuck while working on this requirement? Do you want to get review of your solution? Now, you can book dedicated 1:1 with me on Lightning Web Component completely free.

GET IN TOUCH

Schedule a 1:1 Meeting with me

Also check out https://salesforcediaries.com/category/lightning-web-com

Leave a Reply