2

I have map attribute in lightning component. It has id key and value is true or false for checkbox.

<aura:attribute name="customMap" type="Map" /> 

I want to iterate via array and get value from this map (that is already populated).

<aura:iteration items="{! v.customList }" var="customListItem">
   <lightning:input aura:id="{! customListItem.Id }" type="checkbox" label=" " onchange="{! c.checkCustomMap }" checked="SET_CHECKED_OR_ONCHECKED"/>
</aura:iteration>
2
  • isn't this working <lightning:input aura:id="{! customListItem.Id }" type="checkbox" label=" " onchange="{! c.checkCustomMap }" checked="{!v.customMap[customListItem.Id] }"/> – Ashwani Apr 18 '17 at 17:48
  • Nope, that doesn't work in lightning. – Eugene Vabishchevich Apr 18 '17 at 17:49
2

You can workaround with two more steps:

The Component:

<aura:attribute name="mapObj" type="String[]" />
    <aura:iteration items="{! v.customList }" var="customListItem">
        <aura:iteration items="{!v.mapObj}" var="mapObjItem">
            <aura:if isTrue="{!mapObjItem.key == customListItem.id}">
                <lightning:input aura:id="{! customListItem.Id }" type="checkbox" label=" " checked="{!mapObjItem.value}"/>
            </aura:if>
        </aura:iteration>
   </aura:iteration>

Matching the Map key with the custom list usong aura:if. If key matched then print the checkbox with the value that Map contains. It can be false or true. It will show checkbox for the keys present in Map only.

The controller:-

({
    doInit : function(component, event, helper) {

        // .... logic to set list
        component.set('v.customList', arr);


        // .... setting up the map
        component.set('v.customMap', myMap);

        var mapObj = [];
        for (var prop of myMap.keys()) {
          var mapItem = {};
          mapItem.key = prop;

          // if value is boolean type
          mapItem.value = myMap.get(prop);
          // if value is String. Don't use above statement if this is true.
          mapItem.value = myMap.get(prop) == 'true' ? true : false;
          mapObj.push(mapItem);
        }
        component.set('v.mapObj', mapObj);

    },

    checkCustomMap : function(component, event, helper) {

      // To do
    }
})

Here I converted the Map into object list accessible in the component.

Note: If Map has checkbox value as String, it will check all checkbox regardless of value (true/false). So, it required to be converted in Boolean type for correct re-rendering.

6
  • Good point! What about performance? If I have many rows in the first iteration. – Eugene Vabishchevich Apr 18 '17 at 18:59
  • It is javascript. I don't feel you will see difference. I have iterated list of 10000 accounts in past. It took 5 seconds in normal computer. Since the iteration is by native tags I believe it must be optimized. @EugeneVabishchevich – Ashwani Apr 18 '17 at 19:01
  • That works good! But I have issue with lightning:input checked attribute. That is screenshot: take.ms/p4JU0 Strange, no? – Eugene Vabishchevich Apr 18 '17 at 19:53
  • @EugeneVabishchevich is the vale true/false a String or boolean? – Ashwani Apr 18 '17 at 20:00
  • @EugeneVabishchevich updated the code a little bit. – Ashwani Apr 18 '17 at 20:05
2

I think you will need to build yourself a simple array of true/false values that matches the Map.

In your controller you could build yourself both a keys and values array and use one to work out the other.

var keys = Object.keys(yourMap);
var keyObjects = [];

keys.forEach(function(key){
  var keyObject = {};
  keyObject.key = key;
  keyObject.selected = yourMap[key].selected;
});

component.set('v.keyObjects',keyObjects);

Then use the name attribute to store some data as I don't think pass through values are allowed. If you don't want to do that, use a standard input, it's pretty easy to style them the way you want. You can't use aura:id either, as it gets rewritten.

<aura:iteration items="{! v.keyObjects }" var="obj">
  <lightning:input name="{! obj.key }" type="checkbox" label=" " onchange="{! c.checkCustomMap }" checked="{!obj.selected}"/>
</aura:iteration>

Finally in the checkCustomMap function, you would use the event.getSource() method to get the key via the name attribute.

5
  • Do you think that I need additional iteration for each checkbox? For example I can have about 20 records and for each of this record I need to set checkbox. – Eugene Vabishchevich Apr 18 '17 at 18:58
  • Well, this technique is trying to avoid the iteration that Ashwani's technique uses - you only need one here, with the caveat that you need an extra loop to set it up in the controller. To clarify - you only need one aura:iteration for the whole list. – Caspar Harmer Apr 18 '17 at 19:01
  • The thing is that my list has wrapper class type actually. In my case I need values from the wrapper class in other internal components. And one of variable in wrapper is custom object. Id of this custom object is what I need for my custom checkbox. In this case I think I need to try Ashwani's solution. What do you think? – Eugene Vabishchevich Apr 18 '17 at 19:09
  • You can still expose your Map and use wherever you like - the Array is just a way to iterate the map as discrete objects – Caspar Harmer Apr 18 '17 at 19:12
  • You can even set it up so that you have both a plain Array and a Map pointing to the same wrapper object. The Array is used for any iteration, the Map is used for easy object access. – Caspar Harmer Apr 18 '17 at 19:14

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.