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
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
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
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
Post a Comment