15

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?

  • Updated my answer. You can use a Map. I've verified. – Caspar Harmer Jan 27 '17 at 1:21
16

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
});
| improve this answer | |
  • The more directly applicable version is what I wanted. Thanks. – JaKu Jan 26 '17 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 Jan 26 '17 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!!

| improve this answer | |
  • 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 Jan 27 '17 at 10:21
  • @grayjustice - correct? – Caspar Harmer Jun 18 '18 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 Jun 18 '18 at 8:52
  • Good point. Removed my silly update. – Caspar Harmer Jun 18 '18 at 9:59

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.