Event Propagation

When an event is fired from a component, the aura framework follows a set procedure to move that event from component to component. This movement of the event is called event propagation.

Event propagation is a little different for component and application events. Let’s talk about the component events first.

Propagation in Component Events

Event propagation in component events occurs in the following phases :

  1. Capture Phase
  2. Bubble Phase

Capture Phase

The Capture Phase represents the movement of the event from the root (top-most) component to the component which actually fired the event (source).

Let’s represent that graphically :

The thing of note here is that the event when fired from Component D, travels to the top-most Component A and then stops the propagation in the capture phase. The event is not sent over to the siblings of the Component D, like the Component C and E.

Bubble Phase

After the Capture Phase is finished, the Bubble Phase starts. The Bubble Phase follows the opposite direction of propagation, that is, the event travels from the source component (the one which fires the event) to the top-most component in the hierarchy (root component).

The Bubble Phase also does not propagate over to the sibling components as well.

In the code side of things, we can specify a particular phase to handle in our “aura:handler”. For example :

<aura:handler event="c:MyEvent" 
                  action="{!c.handleEvent}"
                  phase="capture"/>

OR:

<aura:handler event="c:MyEvent" 
                  action="{!c.handleEvent}"
                  phase="bubble"/>

If we don’t specify any phase in the handler, then the default phase being handled is the “bubble” phase for component events.

Propagation in Application Events

Event propagation in application events occurs in the following phases :

  1. Capture Phase.
  2. Bubble Phase.
  3. Default Phase.

Capture Phase

The capture phase in application events behaves exactly the same as component events, that is the event travels from the root (top-most) component to the source(the component which fired the event).

Example :

This means that if we use an application event and explicitly handle the ‘capture’ phase then it behaves the application events behave exactly the same as component events.

Bubble Phase

Again, for the bubble phase it behaves exactly the same as the bubble phase in component events. That is the propagation happens from the source component to the root (top most) component in the hierarchy.

Again this means that we handle the bubble phase for application events, they behave the same way as component events as well.

The code side of things also work the same way for bubble and capture phases. You can explicitly handle either the bubble or phase in the aura handler.

<aura:handler event="c:MyEvent" 
                  action="{!c.handleEvent}"
                  phase="capture"/>

OR:

<aura:handler event="c:MyEvent" 
                  action="{!c.handleEvent}"
                  phase="bubble"/>

Default Phase

There is a third phase called the “default” phase for application events which works differently than the bubble and capture phases.

The default phase travels to all the components in the application which includes siblings as well. This means that we can propagate to all the components in the page,

Event Propagation Methods

There are certain methods which are used to stop or resume the propagation of events. These are as follows :

  1. event.stopPropagation().
  2. event.pause() and event.resume().
  3. event.preventDefault().

event.stopPropagation()

This is used to stop the propagation of an event when you receive it to stop it’s propagation further in the component hierarchy.

Example :

Code :

<aura:handler name="cmpEvent"
                  event="c:MyEvent" 
                  action="{!c.handleEvent}"/>
({
    handleEvent : function(component, event, helper) {        
               event.stopPropagation();    
}
})

If we call this method then this event will not propagate further in the hierarchy. For example if we fire the event from a component A then it is supposed to propagate to a component B then to a component C, that is Cmp A -> Cmp B -> Cmp C. The above code is written in the Cmp B handler for the event, then the event will not move to the component C.

event.pause() and event.resume()

The event pause() and resume() methods are used in conjunction to pause the propagation of an event and resume it based on some custom logic. For example, we might want to pause and event and then call an apex method and since the method runs asynchronously we would resume the event propagation when we get the call back from the apex method.

Code :

<aura:handler name="cmpEvent"
                  event="c:MyEvent" 
                  action="{!c.handleEvent}"/>
({
    handleEvent : function(component, event, helper) {          
event.pause();
        // Resume the event based on some logical condition or in callback
        event.resume();
		}
})

event.PreventDefault()

Calling this method stops the propagation of events in the next phase. That is, if we call this method in the capture phase of a component event then after the capture phase finishes, the bubble phase is not called.

Code :

<aura:handler name="cmpEvent"
                  event="c:MyEvent" 
                  action="{!c.handleEvent}"/>
({
    handleEvent : function(component, event, helper) {        
event.PreventDefault();
}
})

NOTE : This does not stop the propagation of the default phase in case of application events.

EventPropagation.app

<aura:application />	
    <c:ComponentA/> 	
</aura:application/>

ComponentA.cmp

<aura:component />	
    <aura:registerEvent name="cmpEvent" type="c:MyEvent"/>
    <aura:handler name="cmpEvent" event="c:MyEvent" action="{!c.handlEvent}"
                  phase="capture"/>	
    <lightning:button label="CMP A" onclick="{!c.fireEvent}"/> 

<c:ComponentB/<
</aura:component/>

ComponentAController.js

({
	fireEvent : function(component, event, helper) {		
        var cmpEvent = component.getEvent("cmpEvent");
        cmpEvent.fire();
	},    
    handlEvent : function(component, event, helper) {		
        alert('CMP A');
	}
})

ComponentB.cmp

<aura:component />    
    <aura:registerEvent name="cmpEvent" type="c:MyEvent"/>    
    <aura:handler name="cmpEvent" event="c:MyEvent" action="{!c.handlEvent}"
                  phase="capture"/>    
    <lightning:button label="CMP B" onclick="{!c.fireEvent}"/>	
</aura:component/>

ComponentBController.js

({
	fireEvent : function(component, event, helper) {		
        var cmpEvent = component.getEvent("cmpEvent");
        cmpEvent.fire();
	},
        handleEvent : function(component, event, helper) {		
        alert('CMP B');
	}
})
Output :

The example will display the propagation of lighting events from Component A to Component B when the CMP B button is clicked.

Subscribe Now