[SalesForce] Lightning Component event – understanding & clarification

So I was going through this Salesforce doc about event propagation rules: Handling Bubbled or Captured Component Events

What this doc says is that "By default, every parent in the containment hierarchy can’t handle an event during the capture and bubble phases. Instead, the event propagates to every owner in the containment hierarchy.

Now, who is the owner component? So if I have this setup (same what doc examples):

<!--c:owner-->
<aura:component>
    <c:container>
        <c:eventSource />
    </c:container>
</aura:component>

c:owner is the outermost component that's why it is a Parent component and can only handle the component level events fired by c:eventSource.

A note from doc:
"c:container contains c:eventSource but it’s not the owner because it’s not the outermost component in the markup, so it can’t handle the bubbled event.
c:owner is the owner because c:container is in its markup.
c:owner can handle the event."

I thought to go ahead and try this in practice. What I noticed is that component event fired from c:eventSource is handled by both the components in the hierarchy. Here is the code.

eventSource.cmp

<aura:component description="eventSource" access="global">
    <aura:registerEvent name="compEvent" type="c:compEvent" />

    <div class="slds-grid slds-grid_align-center slds-p-vertical_large">
        <div>
            <lightning:button label="Fire Component Event"
                              name="componentevent"
                              onclick="{!c.fireComponentEvent}"
                              variant="brand"/>
        </div>
    </div>
</aura:component>

eventSourceController.js

({
    fireComponentEvent: function (component) {
        var cmpEvent = component.getEvent("compEvent");
        cmpEvent.fire();
    }
})

container.cmp

<aura:component description="container" access="global">
    <aura:handler name="compEvent" event="c:compEvent" action="{!c.handleComponentEvent}"/>

    <c:eventSource />
</aura:component>

containerController.js

({
    handleComponentEvent: function (component,event) {
        console.log("I am in container component");
    }
})

owner.cmp

<aura:component description="owner" access="global">
    <aura:handler name="compEvent" event="c:compEvent" action="{!c.handleComponentEvent}"/>

    <c:container/>
</aura:component>

ownerController.js

({
    handleComponentEvent: function (component,event) {
        console.log("I am in owner component");
    }
})

LightningApp.app

<aura:application extends="force:slds">
    <c:owner/>
</aura:application>

This is screen shot after I click the button. The c:container component should not catch the event during the Propagation cycle.

enter image description here

Am I missing something here in the understanding of the event propagation?

Thanks

Best Answer

There are some fundamental things to understand here :

The component event life cycle has three different stages

1.Event fired—A component event is fired.

2.Capture phase—The framework executes the capture phase from the application root to the source component until all components are traversed. Any handling event can stop propagation by calling stopPropagation() on the event.

3.Bubble phase—The framework executes the bubble phase from the source component to the application root until all components are traversed or stopPropagation() is called.

And the Direction in which propagation happens can be understood by below diagram

enter image description here

In your example your eventSource component is also present in the container component . Hence it is able to handle the event

<aura:component description="container" access="global">
    <aura:handler name="compEvent" event="c:compEvent" action="{!c.handleComponentEvent}"/>

    **<c:eventSource />**
</aura:component>

If the eventSource was not a part of container component then you would not be able to handle it .

Try commenting it from the container component and modify owner component to below

<aura:component description="owner" access="global">
 <aura:handler name="compEvent" event="c:compEvent" action="{!c.handleComponentEvent}"/>
  <c:container/ >
   <c:eventSource />
</aura:component>

Now you will see only owner component is able to handle it .

Check the below blog for a working playground to understand in depth .

Related Topic