Salesforce Lightning Events Part 3 - Bubble and Capture Phase
This blog is in continuation to my previous blog post, so if you haven't read the previous blog at least have a look at the code here as I am not going to embed all the code snippets again in this blog.
As we already know about what component events are and we have also made a small application using component events in previous post. It's time to modify that application a little and learn more about types of phases in component events. You must have read earlier about Bubble and Capture phase in component events in my blog post Salesforce Lightning Events Part 1 - Component Events Introduction. We are going to see these phases in action here.
So, If you remember the code used in my previous blog, I have made a simple component event which will run by default in bubble phase to calculate the total income from the entries present in lightning datatable and pass that total income to the parent component from the source component using an event by clicking on Calculate Total Income Button. When you click on this button, you see the output like this:-
This simply means that, as the lightning event traverse in bubble phase by default, therefore the handler of source component that fired the event is executed first and so we get the alert message - Event handler at source component that fired the event. Moving on to the second output which looks like below:-
This is the event handler defined at the parent component which is executed when the handler at the source component is already executed. As in the bubble phase, the handler at the source component is executed first and then the event is traversed up in the hierarchy and the handler at the parent component is executed.
If you remember, the handler defined at parent component as shown above, after the alert message, we set the value of totalIncome argument. So, we have a final output like this:-
I am going to add one more line in this code and that is event.stopPropagation(); So, my final code is like given below:-
Now when you run this app, you'll see that only output 1 is there and output 2 and 3 didn't came. So, what's the reason behind that ? You guessed it right..!! By default the event is propagating in Bubble Phase therefore, when we added event.stopPropagation(); in the handler defined in source component, the event stopped propagating and it didn't reached the parent component and so we didn't got output 2 and 3. We got only Output 1 in this case.
Okay, so we got the fact that how the events propagate in the bubble phase. Now it's time to move on to the capture phase. Remove the event.stopPropagation(); line so that we are back in the previous state where we were getting all the outputs 1, 2 and 3.
Notice that even the source component is firing the event and it has a handler defined to handle that event still the handler of parent component handles the event first because as the event is fired, it directly go to the application root without the handler being executed at the source component (if any) and then traverse down to the source component that fired the event.
There is a matter of surprise that the Output3 i.e. the updating the total income value should have occurred after output 2 and then output 1 should occur. Yes, you are right and this is only how it's happening but the point is that as the js updated the value of total income it didn't stop executing and the next alert message came up before the effect of change in totalIncome is reflected. The parent component handler is executed before the source component.
To make sure this concept you can add event.stopPropagation(); to the parent component handler function as given below:-
LightningEventsCompContainerController.js - Before adding stop propagation method
LightningEventsCompContainerController.js - After adding stop propagation method
You'll see that the child component handler is not executed as the event stopped propagating after reaching the parent component.So, the order of the output is as follows:- Output 2 -> Output 3.
So, we have seen the bubble phase as well as the capture phase and also the path the event follow in both the phases. But wait, these phases are only associated with event handler right..!!
What will happen when I configure one handler to handle bubble phase and other to handle capture phase ?? Let's figure it out.
Remove the event.stopPropagation(); so that we can continue again from the initial state. As the event run in both the phases, you'll see no change as both the handlers will run when you run one handler in bubble and other in capture phase. But, notice that the handler which is in capture phase run first and the handler which is in bubble phase run after that.
Suppose you only add phase="capture" to LightningEventsComp1.cmp and the LightningEventsCompContainer.cmp runs in bubble phase as default. Given below is the handler in both the files:-
LightningEventsComp1.cmp
LightningEventsCompContainer.cmp
Now, you'll see that the order of output is as follows:- Output 1-> Output 2-> Output 3. So, the source component handler runs in capture phase and is executed first whereas the parent component runs in bubble phase and is executed after that. Before discussing why this happened let's make one more change which is just reverse of this. Let's add phase="capture" to LightningEventsCompContainer.cmp this time and not to LightningEventsComp1.cmp as shown below:-
LightningEventsComp1.cmp
LightningEventsCompContainer.cmp
Now, when you run the app again, you'll see that the order of output is as follows:- Output 2-> Output 1-> Output 3. Make sure that you don't get confused by Output 3 as it's the js delay in changing the value due to which other alert is executed as explained by me earlier. Just focus on Output 1 and Output 2. So, we got to know that this time the handler in LightningEventsCompContainer.cmp was in capture phase and executed first whereas handler in LightningEventsComp1.cmp was in bubble phase and executed later.
So, from this, we can conclude that,
"If handlers of same event are in different phases, then the handlers in capture phase are executed first following their order where as the handlers in bubble phase are executed in their order after the handlers in capture phase have done their execution".
In other words we can say that the capture phase is always handled before the bubble phase. But as we see, both the handlers are executed both the time. So, to have a better understanding, let's consider the previous code in which we have LightningEventsCompContainer in capture phase and LightningEventsComp1 in bubble phase. We are only going to do a single change now i.e. we are going to add event.stopPropagation(); to our handler action which is running in capture phase. So, below is the LightningEventsCompContainerController.js :-
As you can see above, we have added event.stopPropagation(); at the last line. Therefore, when you run the app now, you'll get the output in the following order:- Output 2 -> Output 3. Notice that Output 1 is not there. This is because, the capture phase stopped the event propagation and the event is not propagated in any phase after that. But what if we stop propagating the event in bubble phase ?? If you do so, you'll see that all the handlers that run in capture phase are executed successfully whereas only those handlers in the bubble phase are executed which come before the handler that stop the propagation of the event. I'll leave this to you as an exercise.
As a result, we can say that when an event propagation is stopped in bubble phase, it will not propagate further only in bubble phase as it has already propagated in capture phase before. Whereas, when an event propagation is stopped in capture phase, it'll not propagate further in any phase as the bubble phase as it has already stopped propagating in capture phase and the bubble phase executes after that.
As we already know about what component events are and we have also made a small application using component events in previous post. It's time to modify that application a little and learn more about types of phases in component events. You must have read earlier about Bubble and Capture phase in component events in my blog post Salesforce Lightning Events Part 1 - Component Events Introduction. We are going to see these phases in action here.
So, If you remember the code used in my previous blog, I have made a simple component event which will run by default in bubble phase to calculate the total income from the entries present in lightning datatable and pass that total income to the parent component from the source component using an event by clicking on Calculate Total Income Button. When you click on this button, you see the output like this:-
Output 1 - Alert message from source component that fired the event |
This simply means that, as the lightning event traverse in bubble phase by default, therefore the handler of source component that fired the event is executed first and so we get the alert message - Event handler at source component that fired the event. Moving on to the second output which looks like below:-
Output 2 - Alert message from parent component |
This is the event handler defined at the parent component which is executed when the handler at the source component is already executed. As in the bubble phase, the handler at the source component is executed first and then the event is traversed up in the hierarchy and the handler at the parent component is executed.
({ // Function to handle Lightning Event handleTotalIncomeComponentEvent : function(component, event, helper) { alert('Event handler at the parent component'); // Getting the value of totalIncome attribute of event using event.getParam() var totalIncome = event.getParam('totalIncome'); // Setting the totalIncome attribute of component with the event's totalIncome attribute value. component.set('v.totalIncome', totalIncome); } })
Output 3 - Final change in the totalIncome variable by the parent component handler |
Understanding Bubble Phase in Component Event
Now, let's make a small change in event handler in our source component i.e. in file LightningEventsComp1Controller.js, right now you have the following code:-Okay, so we got the fact that how the events propagate in the bubble phase. Now it's time to move on to the capture phase. Remove the event.stopPropagation(); line so that we are back in the previous state where we were getting all the outputs 1, 2 and 3.
Understanding Capture Phase in Component Event
In our code, firstly move to LightningEventsComp1.cmp file and checkout the handler for event. You'll see something like this:-
Now, in the above code, I am going to add one extra attribute in the handler i.e. the final code is like given below:-
Notice that, I have added another attribute as phase="capture" in the event handler specifying that this event handler will now handle the capture phase of the fired event. Similarly, make this change in the handler present in LightningEventsCompContainer.cmp file. The initial and final versions of the second file are given below:-
Initial Version
Final Version
Now, as you can see in the final version of both the files, the handlers have added the attribute phase="capture". Now let's click on Calculate Total Income button again and check the changes in outputs. You'll see that the order of the output is Output 2 -> Output 1 -> Output 3. Now, we know that in capture phase the event start propagating from the application root. Therefore, the Output 2 i.e. alert in parent component appear before the alert in source component.Initial Version
Final Version
Notice that even the source component is firing the event and it has a handler defined to handle that event still the handler of parent component handles the event first because as the event is fired, it directly go to the application root without the handler being executed at the source component (if any) and then traverse down to the source component that fired the event.
There is a matter of surprise that the Output3 i.e. the updating the total income value should have occurred after output 2 and then output 1 should occur. Yes, you are right and this is only how it's happening but the point is that as the js updated the value of total income it didn't stop executing and the next alert message came up before the effect of change in totalIncome is reflected. The parent component handler is executed before the source component.
To make sure this concept you can add event.stopPropagation(); to the parent component handler function as given below:-
LightningEventsCompContainerController.js - Before adding stop propagation method
So, we have seen the bubble phase as well as the capture phase and also the path the event follow in both the phases. But wait, these phases are only associated with event handler right..!!
What will happen when I configure one handler to handle bubble phase and other to handle capture phase ?? Let's figure it out.
Remove the event.stopPropagation(); so that we can continue again from the initial state. As the event run in both the phases, you'll see no change as both the handlers will run when you run one handler in bubble and other in capture phase. But, notice that the handler which is in capture phase run first and the handler which is in bubble phase run after that.
Suppose you only add phase="capture" to LightningEventsComp1.cmp and the LightningEventsCompContainer.cmp runs in bubble phase as default. Given below is the handler in both the files:-
LightningEventsComp1.cmp
LightningEventsCompContainer.cmp
LightningEventsComp1.cmp
LightningEventsCompContainer.cmp
So, from this, we can conclude that,
"If handlers of same event are in different phases, then the handlers in capture phase are executed first following their order where as the handlers in bubble phase are executed in their order after the handlers in capture phase have done their execution".
In other words we can say that the capture phase is always handled before the bubble phase. But as we see, both the handlers are executed both the time. So, to have a better understanding, let's consider the previous code in which we have LightningEventsCompContainer in capture phase and LightningEventsComp1 in bubble phase. We are only going to do a single change now i.e. we are going to add event.stopPropagation(); to our handler action which is running in capture phase. So, below is the LightningEventsCompContainerController.js :-
As a result, we can say that when an event propagation is stopped in bubble phase, it will not propagate further only in bubble phase as it has already propagated in capture phase before. Whereas, when an event propagation is stopped in capture phase, it'll not propagate further in any phase as the bubble phase as it has already stopped propagating in capture phase and the bubble phase executes after that.
No comments:
Post a Comment