Tuesday, March 22, 2016

Salesforce Lightning Component - Component Event Bubbling Effect

Salesforce Lightning – The Future of Salesforce. Lightning is the collection of tools and technologies behind a significant upgrade to the Salesforce1 Platform. It includes Lightning Component Framework which is used to create reusable components, customize the Salesforce1 App, and also build Standalone apps.

The framework uses the event-driven approach communicate with different components. Event is a notification which will let the world/interested entity know that something happened and now they can take actions accordingly.

In Salesforce Lightning, the interested entity is the components that you develop. The components will register for the events they are interested and will fire if required. And at the same time there will be components who will handle the events when they are fired.

We have two different types of lightning events, as displayed below –
  • Application Event
  • Component Event
In this post, I will try to explain how Component Events are handled in Salesforce Lightning Framework.

Salesforce documentation says, “A component event is always fired from an instance of a component. A component event can be handled by the component that fired the event or by a component in the containment hierarchy that received the bubble event.

I believe this is the best explanation of component event. Later in this post, I will give you an example to explain the bubble effect which I believe is little confusing at this point of time. Let’s wait for some time and I am quite sure once you go through the example below in the post, you will be clear with the component events.

With this agreement, let’s start with few basics:

HOW TO CREATE CUSTOM COMPONENT EVENT:
Below code will create a component event (name: sampleComponentEvent) having one attribute named Country of type String.
<!—Component Event Name: sampleComponentEvent -->
<aura:event type=”COMPONENT”>
 <aura:attribute name=”country” type=”String”/>
</aura:event>

Now to access the parameters of the event, you can use –
event.getParam(“country”);

HOW TO REGISTER CUSTOM COMPONENT EVENT:
A component needs to register for component event if it is willing to fire the event. Below code will register the event sampleComponentEvent.
<aura:registerEvent name=”mySampleComponentEvent” type=”sudipta:sampleComponentEvent />
Note: sudipta is the namespace here. So in your code, you need to replace “sudipta” with your namespace.

HOW TO FIRE CUSTOM COMPONENT EVENT:
To fire an event, you need to first get a reference of the event in JavaScript and then use fire() method to fire the event. Below is the code –
var compEvent = component.getEvent(“mySampleComponentEvent”);
compEvent.fire();

HOW TO HANDLE CUSTOM COMPONENT EVENT:
You need to use <aura:handler> tag to handle custom component event. Below is the code:

<aura:handler name=”mySampleComponentEvent” action=”{!c.handleComponentEvent}” />

Here handleComponentEvent is the name of the JavaScript controller function which will react when the event happens.
With all the above details, let’s go through the below example where I will try to explain the event bubbling effect.

Event – cmpClickEvent:
To start with, let’s create an event – cmpClickEvent.
<aura:event type="COMPONENT" description="Component Click Event" />

Component – clickEventGenerator:
Now the component – clickEventGenerator who will register the above component and also fire the event on button click.
<aura:component >
    <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
    
    <!-- Aura Event Registered -->
    <aura:registerEvent name="clickEvent" type="sudipta:cmpClickEvent"/>
    
    <div class="container">
     <form class="slds-form--stacked">
         <div class="slds-form-element">
                <ui:button label="GENERATE EVENT" labelClass="label" class="slds-button--neutral" press="{!c.fireEvent}"/>
            </div>
        </form>
    </div>
 
</aura:component>

And the JavaScript Controller contains the method –
({
 fireEvent : function(component, event, helper) {
             var cmpEvent = component.getEvent("clickEvent");
             cmpEvent.fire();
 }
})

Another Component – clickEventInnerMostComponent:
This component is the handler of the event. Here is the code –
<aura:component >
 <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
    
    <!-- Aura Event Handler -->
    <aura:handler name="clickEvent" event="sudipta:cmpClickEvent" action="{!c.takeActions}" />
    
    <div>
        <sudipta:clickEventGenerator />
    </div>
</aura:component>

And here comes JavaScript Controller code:
({
 takeActions : function(component, event, helper) {
          console.log("Event handled from Inner Most Component: " + event.getName());
 }
})

Another Component – clickEventMiddleComponent:
This is the component which is also a handler of the event. Here is the code:
<aura:component >
 <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
    
    <!-- Aura Event Handler -->
    <aura:handler name="clickEvent" event="sudipta:cmpClickEvent" action="{!c.takeActions}" />
    <div>
     {!v.body}
    </div>
</aura:component>

And here comes JavaScript Controller code:
({
 takeActions : function(component, event, helper) {
           console.log("Event handled from Middle Most Component: " + event.getName());
 }
})

Another Component – clickEventParentComponent:
This is the parent component as well as handler of the event. Here is the code –
<aura:component >
 <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
    
    <!-- Aura Event Handler -->
    <aura:handler name="clickEvent" event="sudipta:cmpClickEvent" action="{!c.takeActions}" />
    <div>
     <sudipta:clickEventMiddleComponent >
          <sudipta:clickEventInnerMostComponent />
     </sudipta:clickEventMiddleComponent>
    </div>

And here comes JavaScript Controller code:
({
 takeActions : function(component, event, helper) {
     console.log("Event handled from Parent Component: " + event.getName());
 }
})

Now the final Lightning App – ComponentEventApp:
The app contains a very basic structure as –
<aura:application >
    <sudipta:clickEventParentComponent />
</aura:application>

Now when you will execute the app and click on the GENERATE EVENT Button, you will get the below output in the console:
Event handled from Inner Most Component: clickEvent
Event handled from Parent Component: clickEvent

Surprised, right? Why not the log is coming from Middle Component?

So now if you see the event cmpClickEvent is bubbled to clickEventInnerMostComponent and clickEventParentComponent. It is not bubbled to clickEventMiddleComponent. The reason behind is that component clickEventInnerMostComponent and clickEventParentComponent are the facet value provider of the event, but clickEventMiddleComponent is not the facet value provider.

A component can be a facet value provider if that component is the outermost component in the markup.

clickEventInnerMostComponent became facet value provider because it is the outermost component in the markup for the component clickEventGenerator which is generating the event. This is defined in the component code – clickEventInnerMostComponent.

Similarly clickEventParentComponent became facet value provider because it is the outermost component in the markup for the component clickEventGenerator which is generating the event. This is defined in the component code – clickEventParentComponent.

But the component clickEventMiddleComponent is not the facet value provider as the code for the component doesn’t contain any reference of the component clickEventGenerator which is generating the event.

Now if you change the code of clickEventMiddleComponent to make sure this component also contains the reference of the component clickEventGenerator which is generating the event like below –

<aura:component >
 <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
    
    <!-- Aura Event Handler -->
    <aura:handler name="clickEvent" event="sudipta:cmpClickEvent" action="{!c.takeActions}" />
    <div>
     <sudipta:clickEventInnerMostComponent /> 
    </div>
</aura:component>

The console output changes to –
Event handled from Inner Most Component: clickEvent
Event handled from Middle Component: clickEvent
Event handled from Parent Component: clickEvent

It indicates that now clickEventMiddleComponent is also the facet value provider of the event.

I hope you understood the event bubbling effect now as this concept is very important and developer should be very clear to the concept. In my next post, I will explain the Application type event.

If you have any feedback/question, please let me know. Your feedbacks are always welcome.

1 comment:

  1. Nice Infomation salesforce lightning Component my sincere thanks for sharing this post Please Continue to share this post
    Salesforce Training in Chennai

    ReplyDelete