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.
Best Answer
There is no
.set()
method on a Javascript object. Although you have called it a Map when you wrote this: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: