2

I'm having a problem with setting values during component event handling where the values are sent from a child component, during initialization, to the parent component. The values to be set are in a Map attribute, where the key is a string and the value is a string array.

I initially had a null related exception and already tried adding the 'default="{}"' to my parent component's attribute declaration:

<aura:attribute name="fieldValues"
                type="Map"
                default="{}"/>

This gets me over the first hurdle with a null related exception (which I subsequently found was covered in this question). However, when I try to update the map in the component's controller in an event handler I get a different error. The error is shown later, but first the context.

The handler declaration in the parent component is:

<aura:handler name="selectionChanged" event="c:filterSelectionChange" action="{!c.handleFilterSelectionChange}"/>

The handler code looks like this:

handleFilterSelectionChange: function (component, event, helper) {
    var field = event.getSource().get("v.field").fieldPath; // a value from the child component
    var value = event.getParam("value"); // a value from the event

    var fieldValues = component.get("v.fieldValues");

    fieldValues.set(field, value);

    component.set("v.fieldValues", fieldValues);
}

The "filterSelectionChange" event looks like this:

<aura:event type="COMPONENT">
    <aura:attribute name="value" type="String[]"/>
</aura:event>

This event is fired during the initialization of a child component. The child component includes the following:

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

<aura:registerEvent name="selectionChanged" type="c:filterSelectionChange"/>

The child's controller's doInit looks like this:

doInit: function (component, event, helper) {
    var selection = helper.initSelection(component); // returns a string array value

    var selectionChangeEvent = component.getEvent("selectionChanged");

    selectionChangeEvent.setParams({
        value: selection
    });

    selectionChangeEvent.fire();
}

The error I get (which prevents the child from rendering) happens on the line:

fieldValues.set(field, value);

in the parent component's "handleFilterSelectionChange" event handler, see above, and is:

Uncaught Action failed: c:filter$controller$handleFilterSelectionChange [fieldValues.set is not a function]
Callback failed: apex://FilterController/ACTION$getFieldSet
throws at https://xxxx.visualforce.com/auraFW/javascript/a24vMs8Ru7Q5OyxXWeHeyg/aura_prod.js:38:15

Note that I am using Lightning-Out to render the component in a visual force page (though I don't believe that is specifically relevant to this issue).

You can also see (from the error's details) that this is triggered from the callback handler for a server-side controller query "getFieldSet". I know that this works as all the correct processing occurs prior to adding the management of this map of values. To be clear, this server-side action is handled thus in the parent component's controller:

doInit: function (component, event, helper) {
    var action = component.get("c.getFieldSet");

    action.setParams({
        objectType: component.get("v.objectType"),
        fieldSetName: component.get("v.fieldSet")
    });

    action.setCallback(this, function (response) {
        var state = response.getState();

        if (state === "SUCCESS") {
            component.set("v.fields", response.getReturnValue());
        } else {
            ...
        }
    });

    $A.enqueueAction(action);
}

Setting the "v.fields" attribute on the component triggers the rendering of the parent, which in turn creates and renders the children.

Do you know what I'm doing wrong? Is this a limitation due to triggering this flow in child component initialization? Is it linked to Lightning-Out or the handling in a callback for a server-side action (I doubt it)? Or have I used the wrong approach for managing the parent component's "fieldValues" map?

Any suggestions gratefully received.

6

There is no .set() method on a Javascript object. Although you have called it a Map when you wrote this:

<aura:attribute name="fieldValues"
                type="Map"
                default="{}"/>

Lightning pretty much ignores the value in the type there. In most cases, it has no effect. So, the type of the default value is what you actually get in your JS, which is making an JS Object, not a Map.

So, you should write:

fieldValues[field] = value;
  • I had originally used that syntax (but before fixing the "null related exception"), and switched to using the set method based on misunderstanding some documentation I found. So fixing the "null related exception" didn't resolve all my woes. Changing to using the more normal JavaScript approach has resolved this problem. Thanks! – Phil W Mar 19 '18 at 10:16
  • 1
    FYI, the documentation I followed is at developer.salesforce.com/docs/atlas.en-us.lightning.meta/… and this seems to have mistakes in it; both for the default value of the Map (it is null, not an empty object) and for how to set the value in a map (which is where I got "fieldValues.set(field, value)"). – Phil W Mar 19 '18 at 11:30
  • You're right, that documentation is, at best, misleading. The attribute declaration is OK, and the way to set a value in a Map is OK. But, the two don't work together. You can report this to SF docs and they might update it. Last time I reported something, I tweeted them @salesforcedocs – Aidan Mar 19 '18 at 11:59
  • Aidan, I provided feedback on the page itself (whether they will take any notice... we will see!). Thanks again. – Phil W Mar 20 '18 at 12:24

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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