INTRODUCTION/SCENARIO
While working on one of the user stories of Pharma sector for a client based on Chicago, USA; there was a requirement to display Contact records under their parent account record. Also, pagination was needed with a picklist to choose number of records to be displayed on a page.
CHALLENGE
Lightning:treeGrid is useful component for displaying structured data such as hierarchy or forecasting data while dealing with the same object. But there is no functionality available to display records of 2 different objects (In our case, Account and Contact) in the same table while using Lightning:treeGrid.
APPROACH / SOLUTION
To overcome this limitation, I've implemented custom Javascript in the lightning component containing the mechanism to have customized list of Accounts and Contacts with pagination.
Note: This component requires API version 42.0 and later.
treeGridController is a controller class of the lightning components treeGrid utilized to fetch Account object data which has having child Contact
records.
treeGridController.apxc
public class treeGridController {
@AuraEnabled
public static List <Account> getAccountList() {
return [Select Id, Name,
(SELECT Name, Phone, Email FROM Contacts)
From Account
Where Id IN (Select AccountId From Contact)
ORDER BY Name ASC];
}
}
Below are Component & JavaScript files for the reference which i've used to meet the requirement..
treeGrid.cmp
<aura:component controller="treeGridController" implements="flexipage:availableForAllPageTypes" >
<aura:attribute name="resultData" type="Object" access="private"/>
<aura:attribute name="gridColumns" type="List" />
<aura:attribute name="gridData" type="Object" />
<aura:attribute name="gridExpandedRows" type="Object" />
<aura:attribute name="PageNumber" type="Integer" />
<aura:attribute name="TotalPages" type="Integer"/>
<aura:attribute name="currentPage" type="Integer" default="0" />
<aura:attribute name="limit" type="Integer" default="5" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div class="slds-page-header" role="banner">
<ui:inputSelect aura:id="pageSize" label="Display Records Per Page: " change="{!c.onSelectChange}">
<ui:inputSelectOption label="5" text="5" value="true"/>
<ui:inputSelectOption label="10" text="10"/>
<ui:inputSelectOption label="50" text="50"/>
</ui:inputSelect>
</div>
<lightning:treeGrid aura:id="accTree"
columns="{!v.gridColumns}"
data="{!v.gridData}"
expandedRows="{!v.gridExpandedRows}"
keyField="Id"
hideCheckboxColumn = "true"
/>
<div class="slds-clearfix">
<div class="slds-page-header" role="banner">
<div class="slds-float_right">
<lightning:button disabled="{!v.PageNumber == 1}" variant="brand" aura:id="prevPage" label="Prev" onclick="{!c.handlePrev}" />
<lightning:button disabled="{!v.PageNumber == v.TotalPages}" aura:id="nextPage" variant="brand" label="Next" onclick="{!c.handleNext}"/>
</div>
<p class="slds-page-header__title">Page {!v.PageNumber} of {!v.TotalPages}</p>
</div>
</div>
</aura:component>
treeGridController.js
({
doInit : function(component, event, helper) {
var columns = [
{
type: 'url',
fieldName: 'AccountURL',
label: 'Account Name',
typeAttributes: {
label: { fieldName: 'accountName' }
}
},
{
type: 'text',
fieldName: 'Name',
label: 'Contact Name'
},
{
type: 'phone',
fieldName: 'Phone',
label: 'Phone Number'
},
{
type: 'email',
fieldName: 'Email',
label: 'Email'
}
];
component.set('v.gridColumns', columns);
var action = component.get("c.getAccountList");
action.setCallback(this, function(response){
var state = response.getState();
if (state === "SUCCESS" ) {
var resultData = response.getReturnValue();
component.set('v.resultData', resultData);
helper.bindTableData(component, event);
}
});
$A.enqueueAction(action);
},
handleNext : function(component, event, helper){
component.set('v.currentPage',component.get('v.currentPage')+1);
helper.buildTable(component, event);
},
handlePrev : function(component, event, helper){
component.set('v.currentPage',component.get('v.currentPage')-1);
helper.buildTable(component, event);
},
onSelectChange : function(component, event, helper){
component.set('v.currentPage',0);
var pageSize = component.find('pageSize').get('v.value');
component.set('v.limit',pageSize);
helper.buildTable(component, event);
}
})
treeGridHelper.js
({
bindTableData : function(component, event) {
var resultData = component.get('v.resultData');
for (var i=0; i<resultData.length; i++ ) {
resultData[i].accountName = resultData[i]['Name'];
delete resultData[i]['Name'];
resultData[i]._children = resultData[i]['Contacts'];
delete resultData[i].Contacts;
resultData[i].AccountURL = '/'+resultData[i].Id;
}
component.set('v.resultData',resultData);
this.buildTable(component, event);
},
buildTable : function(component, event){
var resultData = component.get('v.resultData');
var limit = component.get('v.limit');
var currentPage = component.get('v.currentPage');
var totalPage = Math.ceil(resultData.length / limit);
var startIndex = currentPage * limit;
var row = [];
var expandedRows = [];
for (var i = startIndex; i < parseInt(startIndex)+parseInt(limit); i++) {
if(resultData[i]){
expandedRows.push(resultData[i].Id);
row.push(resultData[i]);
}
}
component.set('v.gridData', row);
component.set('v.PageNumber',currentPage+1);
component.set('v.TotalPages',totalPage);
component.set('v.gridExpandedRows', expandedRows);
}
})
OUTPUT: