Most probably in Lightning Components, we only deal with Lists to retrieve data from Apex Controller. But there are many scenarios Lists are not enough to retrieve data. So, Maps are very convenient in any simple or complex scenarios. There are very less resources available on it.
So, consider an example of two object (Objects – Consumer & Product) with junction object (Consumer Product).
Relationship as below.
Explanation :
Below I have provided Lightning Component bundle and Apex Class.
Apex Controller :
So, consider an example of two object (Objects – Consumer & Product) with junction object (Consumer Product).
Relationship as below.
Consumer has Master Details to Consumer Product.
Product has Lookup to Consumer Product.
Product has Lookup to Consumer Product.
Scenario to
be implement: I want to show record of Products which are associated with
Consumers in tab view filtered by Product Family.
Below I have provided Lightning Component bundle and Apex Class.
- Take return type of apex method as map<String,List<Consumer_Products__c>>.
- By using force:hasRecordId, I get current Consumer record Id, will query on Consumer Product to get details of Product related to Consumer.
- Then iterate above query and put all data in
Map<String,List<Consumer_Products__c>> CustToProd = new Map<String,List<Consumer_Products__c>>();
- In JS Controller,
var custs = [];
var conts = response.getReturnValue();
for(var key in conts){
custs.push({value:conts[key], key:key}); //Here we are creating the list to show on UI.
}
component.set("v.FamilyMap ",custs);
- Use FamilyMap in lightning component to iterate and show required data.
- First iteration - To iterate over Keys from Map.
<aura:iteration items="{!v.FamilyMap}" var="FirstIteration" indexVar="key">
- Second Iteration - To iterate over Product List.
<aura:iteration items="{!FirstIteration.value}" var="SecondIteration" indexVar="key1">
- Fetch the Product date by using Var - 'SecondIteration' .
{!SecondIteration.Product__r.Name}
Lightning Component -
<aura:component controller="ConsumerProdDetails" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="CustProductDetails" type="Object" />
<aura:handler name="init" value="{!this}" action="{!c.doinit}" />
<aura:attribute name="FamilyMap" type="Map" />
<div>
<div class="slds-page-header">
<h2>
<lightning:icon class="myUniqueClass" iconName="standard:event" alternativeText="Event" />
<span class="boldtext" title="Product 360 View">
<b>Product 360 View</b>
</span>
</h2>
</div>
<lightning:tabset variant="default" >
<aura:iteration items="{!v.FamilyMap}" var="FirstIteration" indexVar="key">
<lightning:tab label="{!FirstIteration.key}" >
<table class="slds-table slds-table--bordered slds-table--fixed-layout slds-max-medium-table--stacked-horizontal">
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<div class="slds-truncate" title="AccountId">Account Id</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Product Name">Product Name</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!FirstIteration.value}" var="SecondIteration" indexVar="key1">
<tr class="slds-hint-parent slds-cell-wrap">
<th data-label="AccountId" scope="row">
<div class="slds-truncate" >
<!--onclick="{!c.StmtData}"-->
<a href="#" tabindex="-1">{!SecondIteration.Id}</a>
</div>
</th>
<td data-label="Product Name">
<div class="slds-truncate" ><ui:outputText aura:id="ProdName" value="{!SecondIteration.Product__r.Name}"/></div>
</td>
</tr>
</aura:iteration>
</tbody>
</table>
</lightning:tab>
</aura:iteration>
</lightning:tabset>
</div>
</aura:component>
JS Controller :
({
doinit : function(component, event, helper) {
var rid = component.get("v.recordId");
var action = component.get('c.returnConsDetail');
action.setParams({Key : rid});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var custs = [];
var conts = response.getReturnValue();
for(var key in conts){
custs.push({value:conts[key], key:key}); //Here we are creating the list to show on UI.
}
component.set("v.FamilyMap ",custs);
}
else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " +
errors[0].message);
}
}
else {
console.log("Unknown Error");
}
}
});
$A.enqueueAction(action);
}
})
Apex Controller :
@auraEnabledNow Add component to Consumer record page by Using App Builder.
public static map<String,List<Consumer_Products__c>> returnConsDetail(String Key){
Set<id> prodId = new Set<id>();
Map<String,List<Product2>> FamToProd = new Map<String,List<Product2>>();
Map<String,List<Consumer_Products__c>> CustToProd = new Map<String,List<Consumer_Products__c>>();
List<Consumer_Products__c> listCustAccs = [Select Id, Product__r.Name, Product__r.Family from Consumer_Products__c where Consumer__c =:key ];
for(Consumer_Products__c ca : listCustAccs){
prodId.add(ca.Product__c);
}
for(Consumer_Products__c CA : listCustAccs){
if(CustToProd.containskey(CA.Product__r.family)){
CustToProd.get(CA.Product__r.family).add(CA);
}else{
List<Consumer_Products__c> chlist = new List<Consumer_Products__c>();
chlist.add(CA);
CustToProd.put(CA.Product__r.family,chlist);
}
}
return CustToProd;
}