Salesforce Interview Questions & Answers Book is now available!

Grab Now

LWC

Conditionally propagate events in LWC

Let's look at how to conditionally propagate event in LWC when bubbles is true and composed is true.

By Teja, ex-Salesforce engineer · Updated September 21, 2020 · 1 min read

There might be a scenario where we have to conditionally propagate (allow/stop) events from crossing the shadow dom (when bubbling is true and composed is true)

This is how the typical syntax looks like when we want to propagate the event out of the shadow dom using composed is true.

this.template.querySelector('.pDiv')
    .dispatchEvent(
    	new CustomEvent(
            "senddata", 
            {bubbles: true, composed: true}
        )
);

What if we want to conditionally control the event propagation out of shadow dom?

These are the sequence of steps in which they will get executed.

  1. User clicks on the button
  2. We are getting the div count that's wrapping lightning-button.
  3. we are bubbling the events and also composed is true, meaning, the events are capable of crossing the shadow boundary.
  4. In child.html we have event handlers on all the div tags wrapping the lightning-button and Step3 is going to invoke the event listener onsenddata.
  5. The method handleSendData gets invoked.
  6. For every iteration we are reducing the div count(fetched in Step2) by 1.
  7. When this.allDivs === 1, it means it reached the top most div and we are stopping the event propagation.

Here is the code demonstrating the whole thing.

<template>
     
     <!-- Though we have event listeners here they will 
          not be invoked since the event propagation 
          is stopped in step7. -->
     <div onsenddata={handleSendData}>
        <div onsenddata={handleSendData}>
            <c-child onsenddata={handleSendData}></c-child>
        </div>
     </div>
</template>
import { LightningElement, track } from 'lwc';

export default class App extends LightningElement {
    handleSendData(event){

        // event.stopPropagation();
        console.log('In parent component');

    }
}
<template>

    <!--Step4: We have event handlers on all the div tags wrapping the lightning-button
        and this is going to invoke the event listener `onsenddata`.
    -->
    <div onsenddata={handleSendData} class="childDiv">
        <div onsenddata={handleSendData} class="childDiv">
            <div onsenddata={handleSendData} class="childDiv">
                <div onsenddata={handleSendData} class="childDiv pDiv">
                
                    <!-- Step1: When user clicks on the button -->
                    <lightning-button label="click" onclick={handleClick}></lightning-button>
                </div>
            </div>
        </div>
    </div>
</template>
import { LightningElement, api } from 'lwc';

/**
 * Show an item
 */
export default class Child extends LightningElement {

    allDivs;

    handleClick(event){
        // Step2: We are getting the div count that's wrapping lightning-button
        this.allDivs = this.template.querySelectorAll('.childDiv').length;
        
        // Step3: we are bubbling the events and also composed is true; 
        // meaning, the events will cross the shadow boundary 
        this.template.querySelector('.pDiv')
                .dispatchEvent(new CustomEvent("senddata", {bubbles: true, composed: true}));
    }

    // Step5: This method gets invoked 
    handleSendData(event){

        console.log('In child component');
        
        // Step7: When allDivs === 1, it means it reached the top most div 
        // and we are stopping the event propagation 
        if(this.allDivs === 1) {
             event.stopPropagation();
        }

        // Step6: For every iteration we are reducing the count by 1.     
        this.allDivs -= 1;
    }
}

Also, I have blogged everything I know about Events in LWC. Give it a look if you are curious.

Learn it by building it

Every course, every code repository, the discussion group and certificates of completion — one subscription.

Keep me in the loop!

Email me when a new episode is published (promise, I will not spam you)

You're signing up to receive emails from Salesforce Casts