Last week I discovered something about Lightning Components I didn’t know about: aura:action. This is an attribute type that you can use to pass actions to a child component, in addition to the other supported attribute types, and it can be specially helpful if you want to decide at component instantiation which actions should the child component perform.
Let’s say that we have a child component like this one:
AuraActionChild.cmp
<aura:component > <aura:attribute name="myAction" type="Aura.Action" /> <lightning:button label="Click me!" onclick="{!v.myAction}"/> </aura:component>
And let’s say we define a parent like the next one:
AuraActionParent.cmp
<aura:component > <c:AuraActionChild myAction="{!c.clap}"/> <c:AuraActionChild myAction="{!c.jump}"/> <c:AuraActionChild myAction="{!c.dance}"/> </aura:component>
AuraActionParentController.js
({ clap : function(component, event, helper) { alert('I am clapping!'); }, jump : function(component, event, helper) { alert('I am jumping!'); }, dance : function(component, event, helper) { alert('I am dancing!'); } })
The result is the next one:
As you can see, we are defining the actions in the parent and passing them to the child at component instantiation, being able to execute a different action each time.
However you have to be very careful, as Aura.Action has some known limitations:
- It is discouraged to use component.set() with the Aura.Action attribute types.
- It is discouraged to use $A.enqueueAction() in the child component to enqueue the action passed to the Aura.Action attribute.
If you need to have something more dynamic, or to overcome these limitations, the recommended way would be to fire an event from the child component that is handled by the parent component to perform the required action.
Let’s implement the previous example in this way:
MyEvent.cmp
<aura:event type="COMPONENT" description="Execute action"/>
AuraActionChild2.cmp
<aura:component > <aura:registerEvent name="myEventInstance" type="c:myEvent"/> <lightning:button label="Click me!" onclick="{!c.fireMyEvent}"/> </aura:component>
AuraActionChild2Controller.js
({ fireMyEvent : function(component, event, helper) { var compEvent = component.getEvent("myEventInstance"); compEvent.fire(); } })
AuraActionParent2.cmp
<aura:component > <aura:handler name="myEventInstance" event="c:MyEvent" action="{!c.handleComponentEvent}"/> <c:AuraActionChild2 aura:id="clapbutton"/> <c:AuraActionChild2 aura:id="jumpbutton"/> <c:AuraActionChild2 aura:id="dancebutton"/> </aura:component>
AuraActionParent2Controller.cmp
({ handleComponentEvent : function(component, event, helper) { var buttonClicked = event.getSource().getLocalId(); if (buttonClicked === 'clapbutton') alert('I am clapping!'); else if (buttonClicked === 'jumpbutton') alert('I am jumping!'); else alert('I am dancing!'); } })
As you can see in the example, in this way you will need to write some extra code, however, we have a finer degree of control, as we could for example add other event handlers dynamically or pass more information to the parent using event attributes. Also, we are more inline with standard practices for components communication.
Here you have a git repo with the code of the examples.
This is awesome. Is there a way I can pass parameters? From child to parent?
LikeLike
I strongly recommend you to use events to do that, as that is the way to do it in LWC.
LikeLike