16

I have a lightning component which enqueues server side action. To that action I need to pass a map as one of the parameters, but it looks like it takes memory address of the object instead.

The client side code that creates the map and calls the server side action:

var action = cmp.get("c.save");
var mapToSend = new Map()
for (var key of valueMap.keys()) {
    mapToSend.set(key, valueMap.get(key))
}
action.setParams({
    "name": cmp.get("v.name"),
    "params": mapToSend
});

In the controller then:

 public static Boolean save(String name, Map<String, Object> params) {

log of the javascript shows nice Map with all the correct fields, but salesforce system log shows just

14:55:16.0 (3172304)|VARIABLE_SCOPE_BEGIN|[41]|name|String|false|false
14:55:16.0 (3188041)|VARIABLE_ASSIGNMENT|[41]|name|"Account"
14:55:16.0 (3191758)|VARIABLE_SCOPE_BEGIN|[41]|params|Map<String,ANY>|true|false
14:55:16.0 (3204719)|VARIABLE_ASSIGNMENT|[41]|params|{}|0x30d2397a

Any Idea why? What those |false|false and |true|false mean in the logs?

1
  • Updated my answer. You can use a Map. I've verified. Commented Jan 27, 2017 at 1:21

2 Answers 2

17

Don't use Map, just use a normal Object. Here's a demonstration:

Apex:

public class LightningMap {
    @AuraEnabled public static void doMap(Map<String, Object> values) {
        System.debug(values);
    }
}

Lightning Controller:

({
    doInit: function(component, event, helper) {
        var action = component.get("c.doMap");
        action.setParams(
            {
                "values": {
                    "Hello": 5,
                    "World": 15
                }
            }
        );
        action.setCallback(this, function(result) {} );
        $A.enqueueAction(action);
    }
})

Demo App:

<aura:application controller="LightningMap">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
</aura:application>

Logged output:

13:16:24.0 (1462121)|USER_DEBUG|[3]|DEBUG|{Hello=5, World=15}

For a more directly applicable version, this is probably what you want:

var mapToSend = {}
for (var key of valueMap.keys()) {
    mapToSend[key] = valueMap.get(key);
}
action.setParams({
    "name": cmp.get("v.name"),
    "params": mapToSend
});
2
  • The more directly applicable version is what I wanted. Thanks.
    – JaKu
    Commented Jan 26, 2017 at 22:03
  • 2
    @JaKu Glad I could help. Not sure why Map doesn't work, since they're basically the same thing as an Object, but I prefer the Object notation anyways, since it feels more... JavaScript-y.
    – sfdcfox
    Commented Jan 26, 2017 at 22:05
2

UPDATE

Ok, I was bugged by this one and made my own test app.

The result is: you CAN have a Map. You just need to make sure it's declared in the markup and has a default="{}" attribute specified (I initially specified some keys, but you don't even need those, just empty braces)

So, component markup:

<aura:component controller="Your_Controller">
    <aura:attribute name="theMap" type="Map" default="{}"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
</aura:component>

Controller code:

({
    doInit : function(component, event, helper) {
        var action = component.get("c.testMap");
        var theMap = component.get("v.theMap");
        //add some params
        theMap["key1"]="blah1";
        theMap["key2"]="blah2";
        action.setParams({
           "params": theMap
        });
        action.setCallback(this, function(result) {} );
        $A.enqueueAction(action);
    }
})

Server side controller:

@AuraEnabled
public static void testMap(Map<String, Object> params){
    System.debug(JSON.serialize(params));
}

So you CAN have a Map. You just need to declare it in the markup! Hooray!!

4
  • The difference is between defining the variable as new Map() and {}, only the second example works probably due to the way JS handles the object. It doesn't matter if the definition is in markup or in code as in @sfdcfox 's answer
    – JaKu
    Commented Jan 27, 2017 at 10:21
  • @grayjustice - correct? Commented Jun 18, 2018 at 5:46
  • 1
    @CasparHarmer That's not exactly the same issue, though. Why should we have to declare something in markup something that will only be used to send params to the server?
    – sfdcfox
    Commented Jun 18, 2018 at 8:52
  • Good point. Removed my silly update. Commented Jun 18, 2018 at 9:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .