Skip to main content

How to create Dynamic Generic Tree grid using LWC

Hello frnds todat i am talking about , how to create tree-grid using lwc
Step-1:- First create Custom metadata, Click setup and In Quich Search box type " Custom metadata "
Step-2:- Click on Custom metadata and click on "New custom metadata type"
type custom metadata name and save
after that create custom feilds, list given below image

after that click on "manage" enter field api name according to your requirement
Example given below
Step-3:- Create Apex class Name is "SLMT_GenericHierarchiesController"
global class SLMT_GenericHierarchiesController { @AuraEnabled(cacheable=true) global static List getFullHierarchies(Id recordId,String parentRelationship){ Id topLevelParentId = SLMT_GenericHierarchiesController.getUltimateParent(recordId,parentRelationship); List treeColumns = SLMT_GenericHierarchiesController.describeHierarchyMappings(recordId); List additionalFields =new List(); for(TreeNodeColumns rec:treeColumns){ additionalFields.add(rec.fieldName); } List treeNodes = SLMT_GenericHierarchiesController.getTreeNodes(new List{topLevelParentId}, parentRelationship, additionalFields); system.debug('===treeNodes'+treeNodes); return treeNodes; } @AuraEnabled(cacheable=true) global static List describeHierarchyMappings(Id recordId) { String sobjectName = recordId.getSObjectType().getDescribe().getName(); // all recordIds need to be same type List hierarchyMapping = [SELECT SLMT_Column_Field_API__c,SLMT_Column_Label__c,SLMT_Field_Type__c,SLMT_Sort_Order__c FROM SLMT_Hierarchy_Setting__mdt WHERE SLMT_SObject_Name__c = :sObjectName AND SLMT_Show_Hide__c=true ORDER By SLMT_Sort_Order__c ASC]; List columnsList = new List(); for(SLMT_Hierarchy_Setting__mdt rec:hierarchyMapping){ //TreeNodeColumns col = new TreeNodeColumns(rec.SLMT_Field_Type__c,rec.SLMT_Column_Field_API__c,rec.SLMT_Column_Label__c); TreeNodeColumns col = new TreeNodeColumns(); col.label = rec.SLMT_Column_Label__c; col.type = rec.SLMT_Field_Type__c; col.fieldName = rec.SLMT_Column_Field_API__c; if(col.fieldName == 'Name'){ col.cellAttributes = new CellAttribute(); col.cellAttributes.iconName = new Icons(); col.cellAttributes.iconName.fieldName = 'isCurrentRecord'; col.cellAttributes.iconPosition ='right'; col.cellAttributes.iconAlternativeText ='Current Record'; } columnsList.add(col); } return columnsList; } @AuraEnabled(cacheable=true) global static Id getUltimateParent(Id recordId, string parentRelationship) { // Get ultimate parent by checking 5 hierarchy levels per SOQL-query recursively Id retId = null; parentRelationship = String.escapeSingleQuotes(parentRelationship); String sobjectType = recordId.getSObjectType().getDescribe().getName(); String q = 'SELECT Id, ' + parentRelationship + '.Id, ' + parentRelationship + '.' + parentRelationship + '.Id, ' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.Id, ' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.' + parentRelationship + '.Id , ' + parentRelationship + '.' + parentRelationship + '.' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.Id FROM ' + sobjectType + ' WHERE Id = :recordId'; List sobjList = Database.query(q); if(sobjList.size() == 1) { Id l1, l5 = null; try { // try from first to 5th level to get parent Id // Exception will happen at first null value l1 = (Id) sObjList[0].getSobject(parentRelationship).get('Id'); l1 = (Id) sObjList[0].getSobject(parentRelationship).getSobject(parentRelationship).get('Id'); l1 = (Id) sObjList[0].getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).get('Id'); l1 = (Id) sObjList[0].getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).get('Id'); l5 = (Id) sObjList[0].getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).getSobject(parentRelationship).get('Id'); } catch (NullPointerException ex) { // Do nothing, l1 is last Id before exception if no more levels up // System.debug('Exception'); } if( l5 != null ) { retId = getUltimateParent(l5, parentRelationship); } // top level still have parent, do recursive call to check another five levels else if( l1 != null ) { retId = l1 ; } else { retId = sObjList[0].Id;} } system.debug('DEBUG: ' + retId); return retId; } global with sharing class TreeNode { @AuraEnabled global Sobject nodeObj; @AuraEnabled global List children; global TreeNode(Sobject obj) { // constructor adds empty child list nodeObj = obj; children = new List(); } } global with sharing class TreeNodeColumns { @AuraEnabled global string type{get;set;} @AuraEnabled global string fieldName{get;set;} @AuraEnabled global string label{get;set;} @AuraEnabled global CellAttribute cellAttributes{get;set;} } global with sharing class Icons{ @AuraEnabled global string fieldName{get;set;} } global with sharing class CellAttribute{ @AuraEnabled global Icons iconName{get;set;} @AuraEnabled global string iconPosition{get;set;} @AuraEnabled global string iconAlternativeText{get;set;} } @AuraEnabled(cacheable=true) global static List getTreeNodes(List recordIds, string parentRelationship, List additionalFields) { parentRelationship = String.escapeSingleQuotes(parentRelationship); String additionalStr = additionalFields.size() == 0 ? '' : String.escapeSingleQuotes(String.join(additionalFields, ', ') + ','); String sobjectType = recordIds[0].getSObjectType().getDescribe().getName(); // all recordIds need to be same type String q = 'SELECT Id, '+ additionalStr + parentRelationship + '.Id FROM ' + sobjectType + ' WHERE Id IN :recordIds OR ' + parentRelationship + '.Id IN :recordIds OR ' + parentRelationship + '.' + parentRelationship + '.Id IN :recordIds OR ' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.Id IN :recordIds OR ' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.' + parentRelationship + '.Id IN :recordIds OR ' + parentRelationship + '.' + parentRelationship + '.' + parentRelationship + '.' + parentRelationship +'.' + parentRelationship + '.Id IN :recordIds ORDER BY ' + additionalFields[0]; List sobjList = Database.query(q); Map TreeMap = new Map(); List retNodes = new List(); for (Sobject sobj : sobjList) { TreeNode tn = new TreeNode(sobj); TreeMap.put(sobj.Id, tn); } List level5Ids = new List(); for (Sobject sobj : sobjList) { if(recordIds.contains(sobj.Id) ) { retNodes.add(TreeMap.get(sobj.Id)); } else { Id parentId = (Id) TreeMap.get(sobj.Id).nodeObj.getSobject(parentRelationship).get('Id'); TreeNode child = TreeMap.get(sobj.Id); TreeNode parent = TreeMap.get(parentId); TreeMap.get(parentId).children.add(child); } } for (Sobject sobj : sobjList) { if(TreeMap.get(sobj.Id).children.size() == 0 && !recordIds.contains(sobj.Id) ) { try { Id l1, l2, l3, l4, l5; l1 = (Id) TreeMap.get(sobj.Id).nodeObj.getSobject(parentRelationship).get('Id'); l2 = (Id) TreeMap.get(l1).nodeObj.getSobject(parentRelationship).get('Id'); l3 = (Id) TreeMap.get(l2).nodeObj.getSobject(parentRelationship).get('Id'); l4 = (Id) TreeMap.get(l3).nodeObj.getSobject(parentRelationship).get('Id'); l5 = (Id) TreeMap.get(l4).nodeObj.getSobject(parentRelationship).get('Id'); level5Ids.add(sobj.Id); } catch (NullPointerException ex) { } } } if(level5Ids.size() > 0) { List nextChildList = getTreeNodes(level5Ids, parentRelationship, additionalFields) ; for(TreeNode t : nextChildList) { TreeMap.get((Id) t.nodeObj.get('Id')).children = t.children; } } system.debug('==retNodes'+retNodes); return retNodes; } }
Step-4:- create LWC component name "GenericHierarchyView"
slmtGenericHierarchyView.html

slmtGenericHierarchyView.js
import { LightningElement ,api, track} from 'lwc'; import getFullHierarchies from '@salesforce/apex/SLMT_GenericHierarchiesController.getFullHierarchies'; import describeHierarchyMappings from '@salesforce/apex/SLMT_GenericHierarchiesController.describeHierarchyMappings'; export default class GenericHierarchyView extends LightningElement { @api recordId; @track contractData; @track currentExpanded; @api sObjectName; @api parentRelationship; @api headerName; @api contractColumns; @api retCols; connectedCallback(){ this.fetchContractColumns(); } fetchContractColumns(){ describeHierarchyMappings({recordId : this.recordId}) .then(result=>{ this.contractColumns = result; this.retCols = []; this.contractColumns.forEach(element => { this.retCols.push(element.fieldName); }); console.log('====columns'+JSON.stringify(this.contractColumns)); this.fetchSLMTContractView(); }) .catch(error=>{ console.error('--- error ocur when records fetch--',error); }) } fetchSLMTContractView(){ getFullHierarchies({recordId : this.recordId, parentRelationship :this.parentRelationship }) .then(result=>{ console.log('====result'+JSON.stringify(result)); let transverseData = this.traverseNodes(result); this.currentExpanded = result[0].nodeObj.Name; this.contractData = transverseData; this.clickToExpandAll(); }) .catch(error=>{ console.error('--- error ocur when records fetch--',error); }) } traverseNodes (nodes) { let retArr = []; nodes.forEach(element => { let retObj = {}; this.retCols.forEach(ele => { console.log('===element[ele]'+element[ele]); retObj[ele] = element.nodeObj[ele] }); console.log('===element.nodeObj.Id'+element.nodeObj.Id); retObj.Id = element.nodeObj.Id; retObj.isCurrentRecord = element.nodeObj.Id === this.recordId ? 'utility:success' : ''; retObj.isCurrentRecordStyle= element.nodeObj.Id === this.recordId ? 'font-size:140px;bg-color:red;' : ''; retObj.expanded =(this.view == 'All Levels') || (this.view == 'First Level' && element.nodeObj.Id == this.ultimateParentId); if(element.children.length > 0) { retObj._children = this.traverseNodes(element.children); } console.log('==retObj=='+JSON.stringify(retObj)); retArr.push(retObj); } ); return retArr; } clickToExpandAll() { const grid = this.template.querySelector('lightning-tree-grid'); grid.expandAll(); } clickToCollapseAll( e ) { const grid = this.template.querySelector('lightning-tree-grid'); grid.collapseAll(); } }
GenericHierarchyView.css
.hightlightBC { color : red !important; font-weight: bold; }
GenericHierarchyView.js-meta.xml
54.0 true lightning__RecordPage lightning__HomePage
Now our component is ready used , so now i am dragging this component in lightning page
Step-5:- Click on setup then click on "Edit Page "

after edit page , then search component in left side and after drag your component any where , I have draged in right , view given below image

Resutl showing below

Thanks!
Ashish Madhukar

Comments

Popular posts from this blog

How to Create Copy to Clipboard or How to Create Clipboard in Lightning Component

Hello friends today post,, How to Create Copy Clipboard in Lightning Component so let us start...... Step=>1.        goto developer Console......                                     File=>New=>Lightning Component                                                                         copyToClipboard.cmp  <aura:component implements="flexipage:availableForAllPageTypes" access="global" >     <div>         <p aura:id="pId">quick brown fox jumps over the lazy dog</p>         <lightning:button iconName="utility:copy_to_clipboard"                           onclick="{!c.copyHardcoreText}"                           label="Copy Text to clipboard"                           aura:id="btn1"/>     </div>       <div>         <lightning:textarea value="hello i am textarea value" aura:id="inputF"/>         <lightning:button iconName

How to show Current User Profile Picture in Lightning Component

Hello frnds today post learn how to show current user profile picture in lightning component so let us start....... Step=>1.            goto developer console and create lightning component               File=>New=>Lighning Component                DisplayUserPhoto.cmp <aura:component controller="LoginUserProfileCtrl"                 implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"                 access="global" >     <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>     <aura:attribute name="oUser" type="user" default="{'sobjectType' : 'User'}" />     <h1>Current User Profile Picture</h1>     <div style="padding:100px">         <img src="{!v.oUser.FullPho

How to Create Quick Email Sending in Lightning Component

Hello friends today post, how to send Email using lightning component so let start .... Step=>1. first open your developer console and goto...                                                                          File=>New=>Lightning Component                                    EmailSend.cmp <aura:component controller="EmailSendController" implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >         <aura:attribute name="email" type="string"/>     <aura:attribute name="subject" type="string"/>     <aura:attribute name="body" type="string"/>     <aura:attribute name="mailStatus" type="boolean" default="false"/>         <div class="slds-box" style="width:700px;margin-top:10px;margin-left:10px;">     <div class="sld