18

Is it possible to iterate over a Map in an aura:iteration. It doesn't give me a compile or runtime error but it doesn't appear to work.

My thought is that it works similarly to $.each in jquery.

<aura:attribute type="Map" name="myMap"  default="{key1: 'item1', key2: 'item2'}" />       
<aura:iteration items="{!myMap}" indexVar="key" var="item">
      {!key} : {!item} 
</aura:iteration>
| improve this question | | | | |
  • What is actually in myMap? It's possible that default value may not be working. – Kris Gray Jun 5 '15 at 17:11
  • Also pretty sure this would work over a list, but I don't think it works over maps. – Kris Gray Jun 5 '15 at 17:12
  • I used default value just as a simple example but in my actual component it's a parameter being fetched from the server. It does work if I use a list instead and I could work around the issue by having a response object that contains the key and value in the object but it would just be a lot more elegant if I could use the map directly – Scott Morrison Jun 5 '15 at 18:22
  • I have a solution for this. We could create a child component that will accept the map and its key. So based on key we will get the value – Ratan Paul May 24 '16 at 13:45
11

According to the Aura docs it looks like this is only defined to iterate over a List.

If you have not seen the Aura docs app before it is available with any Salesforce instance by modifying the URL:

[your instance stuff].salesforce.com/auradocs/reference.app

Or to navigate to the page for the iteration component:

[your instance stuff].salesforce.com/auradocs/reference.app#reference?descriptor=aura:iteration&defType=component
| improve this answer | | | | |
5

I came across this question and was a little discouraged, but looks like things might have changed since some of these answers were provided.

I found this page in the Lightning Components documentation. All the way at the bottom, and really easy to overlook is what appears to be instructions for iterating over an Apex Map returned from a server-side controller.

I tried it out and it actually works! This controller function populates a picklist <ui:inputSelect ... /> in a Lightning Component by iterating over an Apex Map.

I guess this doesn't exactly answer the original question, but maybe the workaround is to do the iteration in a controller function and provide those results to the view.

({
    doInit : function(component, event, helper) {
        // Create the action
        var action = component.get("c.getApexMap");
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            var state = response.getState();
            console.log(state);
            if (component.isValid() && state === "SUCCESS") {
                //loop through map returned from Server, populating client picklist as we go

                var clientMap = response.getReturnValue();     //the apex map returned from server
                var opt = new Array();                         //this will be our picklist options

                for(key in clientMap) {     //this iterates over the returned map
                    opt.push({ class: "optionClass", label: clientMap[key].labelField__c,
                                                     value: clientMap[key].valueField__c });
                }

                component.find("myPicklist").set("v.options", opt);
            } else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);
    }
})
| improve this answer | | | | |
3

Not a straight Yes to the original question. The Maps can not go in directly, but we can use some thing like this.

Maps or list, all the collections are same for lightning components as it considers all these variables as json.

Try the following: Component:

    <aura:component >

    <aura:attribute name="colercodes" type="list"/> 
    <ui:button press="{!c.getColCodes}" label="Display Colors" />
    <aura:iteration items="{!v.colercodes}" indexVar="key" var="col">
        <p>
            <aura:set attribute="style" value="{!col.BGvalue}"/>
            {!key}: {!col.key} - {!col.value}
        </p>
    </aura:iteration>

</aura:component>

ComponentController.js:

({
    getColCodes: function(component) {
        var cols = []; 
            cols.push({
                value: '#F0F8FF',
                BGvalue: 'background:#F0F8FF',
                key: 'AliceBlue'  
        });
            cols.push({
                value: '#00FFFF', 
                BGvalue: 'background:#00FFFF',
                key: 'Aqua'  
        });
            cols.push({
                value: '#FAEBD7',
                BGvalue: 'background:#FAEBD7',
                key: 'AntiqueWhite' 
        });
            cols.push({
                value: '#7FFFD4',
                BGvalue: 'background:#7FFFD4',
                key: 'Aquamarine'  
        });

        component.set("v.colercodes", cols);
    }
})

===================

I happened to use something like this in one of my projects:

({
    doInit : function(component, event, helper) {
        var action = component.get("c.returnArticles");//Fetching Map/queryresult from Controller
        action.setCallback(this, function(a) {
            component.set("v.ArticleMap", a.getReturnValue()); 
            var Arts = component.get("v.ArticleMap"); 
              console.log(Arts); 
            var artsTemp = [];
            for (Art in Arts){
                console.log(Art);
            var temp =  Arts[Art]
            for (keyofMap in temp){ 

                //pushing the articles into Map/ List of component attribute
                artsTemp.push({
                    key: keyofMap,
                    value: temp[keyofMap]
                });
            } 
            }
            component.set("v.ArticleList", artsTemp);

        });
        $A.enqueueAction(action);
    }
})

Note: I was returning database.query() from the apex controller there.

We can not directly use the maps like we do in VF pages, we can pass that maps to json variable as they are and use them in components.

HTH

| improve this answer | | | | |
  • It looks to me as though you are using an object array rather than a map no? For me a map is something that you can get a value of like this: objectName.keyName – swervo Mar 4 '16 at 15:12
  • This is not a way to iterate a map but a list. – Leisure Jun 28 '16 at 6:47
  • This works for me. Especially after spending considerable time searching for a workable example of iterating over a map (the recommended SF way). – Bryan Jun 9 '18 at 18:08
0
  • Write a wrapper Class for your Map which consists on the map(consider 'myMap') and set of keys(conisder 'myKeys').
  • Create an attribute(Consider 'myWrapper') of the wrapper class.
  • In you can get all the keys by {!myWrapper.myKeys}.
  • In the controller, for getting the value of specific key, use

    var testMap = component.get('v.myWrapper');

    var value = testMap.myMap[key];

| improve this answer | | | | |
0

Like @Prabhan I found that using object array in the client side component was the only way to get iteration to work.
My question was "With Lightning Components how can you iterate over a client side list of objects or map?"

Maybe someone can improve on this or show a complete example in the docs. In my case I needed to display a list of properties from a Case record.

BetaCaseController

public with sharing class BetaCaseController {
    @AuraEnabled
    public static Case getCase(Id id) {
        Case aCase = [
            select Id, ParentId, CaseNumber, CreatedDate, Description, IsClosed, IsDeleted, Origin, OwnerId, Priority, Reason, Status, Subject, Type, ClosedDate, AccountId, ContactId
            from Case WHERE Id = :id
         ];
        // Perform isAccessible() check here 
        return aCase;
    }
}

BetaComponent

<aura:component controller="BetaCaseController"
    implements="flexipage:availableForRecordHome,force:hasRecordId"
    access="global">
    <aura:attribute name="theCase" type="Case" />
    <aura:attribute name="properties" type="list" />
    <aura:attribute name="recordId" type="String" />
    <aura:attribute name="message" type="String" default="empty" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <div class="slds-form" role="list">
        <aura:iteration items="{!v.properties}" indexVar="key" var="prop">
            <div class="slds-grid slds-gutters_small">
                <div class="slds-col slds-has-flexi-truncate" role="listitem">
                    <div
                        class="slds-form-element slds-form-element_edit slds-hint-parent">
                        <div class="slds-form-element__label">{!prop.label}</div>
                        <div class="slds-form-element__control">{!prop.value}</div>
                    </div>
                </div>
            </div>
        </aura:iteration>
    </div>
    <div>T8</div>
</aura:component>

BetaComponentComponent.js

({
    doInit : function(component, event, helper) {
        var action = component.get("c.getCase");
        action.setParams({"id": component.get("v.recordId")});
        action.setCallback(this, function(response){
            var state = response.getState();
            component.set("v.message", state);
            if (state === "SUCCESS") {
                var theCase = response.getReturnValue();
                component.set("v.theCase", theCase);
                var properties =  [];
                properties.push({ 'label' : 'CaseNumber', 'value': theCase.CaseNumber});
                properties.push({ 'label' : 'Subject', 'value': theCase.Subject});
                properties.push({ 'label' : 'Status', 'value': theCase.Status});
                properties.push({ 'label' : 'Parent', 'value': theCase.Parent});
                properties.push({ 'label' : 'IsClosed', 'value': theCase.IsClosed});
                component.set("v.properties", properties);
            }
        });
        $A.enqueueAction(action);       
    },   
})
| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.