[SalesForce] Iterating Complex Map in Lightning

I'm working a lightning component, which has a requirement of displaying a dynamic table.

For that, I need to iterate over a map (Map>) and display the values.

So, How can I retrieve map from apex controller and display values/key on the component ?

Apex Controller method signature –

public static Map<Id, Map<String, String>> getDataCollectionTableValues(Id dataCollectionId){

Apex method return value –

{  
   a0E0k000003aEKUEA2=   {  
      Field_10__c=test1,
      Field_1__c=test2,
      Field_2__c=test3,
      Field_3__c=test6,
      Field_4__c=null,
      Field_5__c=null,
      Field_6__c=test7,
      Field_7__c=null,
      Field_8__c=null,
      Field_9__c=test,
      ...
   }
}

Lightning helper –
I’ve passed id parameter to controller method and set response to the map attribute.

({
    loadDataCollection: function(component) {

        var action = component.get("c.getDataCollectionTableValues");
        action.setParams({
            dataCollectionId : component.get("v.recordId")
        });

        action.setCallback(this, function(response)
        {
            var state = response.getState();
            if (state === "SUCCESS")
            {
                component.set("v.dataCollectionRecords", response.getReturnValue());
                 console.debug(response.getReturnValue());
            }else
            {
                console.debug(response.error[0].message);
            }
        });
        $A.enqueueAction(action);
    }
})

Component –

<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global" controller="DataCollectionTableController">
    <aura:attribute name="recordId" type="Id"/>
    <aura:attribute name="dataCollection" type="Data_Collection__c" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:attribute name="dataCollectionRecords" type="Map"/>
    <aura:iteration items="{!v.dataCollectionRecords}" var="dcrRecord" indexVar="key">
        {!key}
        {!dcrRecord.key}
    </aura:iteration>

</aura:component>

Best Answer

Well Aura:iteration does not support map. Thus you to write your own parser which will convert the Map into a list of custom javascript object that can be iterated by aura: iteration.

Assuming this is the response from the Apex controller.

{  
   a0E0k000003aEKUEA2=   {  
      Field_10__c=test1,
      Field_1__c=test2,
      Field_2__c=test3,
      Field_3__c=test6,
      Field_4__c=null,
      Field_5__c=null,
      Field_6__c=test7,
      Field_7__c=null,
      Field_8__c=null,
      Field_9__c=test,
      ...
   }

}

We will iterate over Outer Map and then over Inner Map, this will allow us to create Javascript object which we will then pass to aura:iteration.

({
    loadDataCollection: function(component) {

        var action = component.get("c.getDataCollectionTableValues");
        action.setParams({
            dataCollectionId : component.get("v.recordId")
        });

        action.setCallback(this, function(response)
                           {
                               var state = response.getState();
                               if (state === "SUCCESS")
                               {
                                   var map = response.getReturnValue();
                                   var parsingWarpper=[];
                                   console.log(map);

                                   //Iterate over the key for Outer Map
                                   Object.keys(map).forEach(function(key) {

                                       var individualElement = {};
                                       individualElement.Id = key;
                                       individualElement.Value =[];
                                       var innerMapObject =map[key];

                                       console.log(innerMapObject);
                                       //Iterate over the key for Inner  Map
                                       Object.keys(innerMapObject).forEach(function(key2) {
                                           console.log(key2);
                                           var innerIndivididualElement ={};
                                           innerIndivididualElement.Key = key2;
                                           innerIndivididualElement.Value = innerMapObject[key2];

                                           individualElement.Value.push(innerIndivididualElement);
                                       });  
                                       parsingWarpper.push(individualElement);


                                   });
                                   console.log(parsingWarpper);
                                   component.set("v.myMap",parsingWarpper);
                               }else
                               {
                                   console.debug(response.error[0].message);
                               }
                           });
        $A.enqueueAction(action);
    }
})

// Your component will be:

    <aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global" controller="DataCollectionTableController">
    <aura:attribute name="recordId" type="Id"/>
    <aura:attribute name="dataCollection" type="Data_Collection__c" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:attribute name="dataCollectionRecords" type="Map"/>
    <aura:attribute type="Object" name="myMap" ></aura:attribute>


    <aura:iteration items="{!v.myMap}" var="ele" indexVar="key">

        {!ele.Id} <br></br>
        <aura:iteration items="{!ele.Value}" var="ele2" indexVar="key2">
            {!ele2.Key} ---> {!ele2.Value} <br></br>

        </aura:iteration>
        <hr></hr>
    </aura:iteration>

</aura:component>

As its nested object, we have to iterate the inner iteration using aura:iteration again.

The resultant looks like what you want.

enter image description here

Related Topic