Mastering Child-to-Parent Communication in Lightning Web Components (LWC)

As we are diving deeper into Lightning Web Components (LWC) and we are getting familiar with the component-based structure in LWC, which is the ground work for building scalable applications in Salesforce. We understand that interfacing components require to communicate among them. But one thing that can be tricky even for seasoned developers, is mastering communication between components.

Child-to-Parent Communication in Lightning Web Components

Today, we will go through the concepts to master Child-to-Parent communication in Lightning Web Components (LWC), which is a common scenario when working with hierarchical components. Let’s break it down step-by-step so you can grasp more easily and confident handling this in your future projects.

How to implement child-to-parent communication in Lightning Web Components

In LWC, components follow a unidirectional data flow, meaning data typically moves from a parent component to its child through properties/attributes. However, there are plenty of situations where a child component needs to send data back up from the child-to-parent component.

For instance:

  • A child form component might need to notify the parent when the user submits the form.
  • A child modal component could send a “close” signal to its parent when the form is submitted/rejected.
  • A child item in a list might pass some selected data back to the parent.

The ability to effectively communicate from child to parent is pivotal to building interactive and dynamic user interfaces.

Step-by-step guide to child-to-parent communication in Lightning Web Components

In LWC, the events are the primary mechanism for child-to-parent communication. The child component “dispatches” an event, and the parent “listens” for that event to handle it. There are different standard events we have used already in previous lessons like onclick, onkeyup, etc. Here we will be learning about the custom events.

Let’s get practical with an example!

1. Dispatching an Event

Let’s say we have a child component that needs to send some data back to the parent component on click on a button.

Here’s the child component’s HTML:

Example childComponent.html

<template>
<lightning-button

label="Send to Parent"
onclick={handleClick}>
</lightning-button>
</template>

And here in the JavaScript for the child component, we create and dispatch a custom event with the message attached on the detail. We can choose to send or not send any details while dispatching the event.

Example childComponent.js

import { LightningElement } from 'lwc';

export default class ChildComponent extends LightningElement {
handleClick() {


// Step 1: Create a new custom event
const customEvent = new CustomEvent('sendtoparent', {
detail: { message: 'Hello from Child!' }
});


// Step 2: Dispatch the custom event
this.dispatchEvent(customEvent);
}
}

Explaination :

  1. Dispatching the Event: We use the this.dispatchEvent(customEvent) to dispatch the event, which can then be listened to, by the parent component.
  2. CustomEvent Creation: In the handleClick method, we create a new custom event using CustomEvent. The event name is 'sendtoparent' (you can name this anything you like, but keep it meaningful). The detail object contains the data we want to send from child to parent component. Here, we are sending a simple message 'Hello from Child!'.

Best Practices for naming an event in LWC

We must choose an only string name, with no uppercase and no spaces. We can use underscores but must keep it smaller but contextual.

2. Listening for the Event in the Parent Component

Now, on the parent component (parentComponent), where we will add an event listener to listen to the event and handle the data sent by the child.

How to handle events in Lightning Web Components?

We add the event listener (on+eventname) onsendtoparent={handleEventFromChild} on the parent component’s HTML:

Example parentComponent.html

<template>
<p>Message from Child: {messageFromChild}</p>
<c-child-component onsendtoparent={handleEventFromChild}></c-child-component>
</template>

And then on the JavaScript for the parent component we handle the event and retrieve any details if there:

Example parentComponent.js

import { LightningElement } from 'lwc';

export default class ParentComponent extends LightningElement {
messageFromChild;
handleEventFromChild(event) {


// Step 3: Capture the event detail
this.messageFromChild = event.detail.message;
}
}

Explaination :

  1. Listening to the Event: In the parent’s HTML template, we use the <c-child-component> tag to include the child component. Here, we add the event listener onsendtoparent={handleEventFromChild}. The sendtoparent matches the event name we dispatched from the child.
  2. Handling the Event: In the parent’s JavaScript, the handleEventFromChild method is triggered when the event is caught. The event.detail.message contains the data passed from the child, which we then store in the messageFromChild property and display in the template.

3. Key Takeaway Points to Remember

  • CustomEvent: Use the CustomEvent constructor to create your event and pass data via the detail property. Keep your event names clear and descriptive.
new CustomEvent('showprompt',{details:null})

There are other two parameters apart from the details here, which are default false as below. We will learn more about bubbles, and composed on the next sub topic in this chapter itself.

new CustomEvent('showprompt',{bubbles:false, composed:false, details:null})
  • dispatchEvent: Always use this.dispatchEvent() to dispatch the event from the child component. We can also send and dispatch as below:
this.dispatchEvent(new CustomEvent('showprompt',{details:null}))
  • Event Listener in Parent: In the parent component’s template, use on<eventname> to listen for the custom event, and define a handler function to process the event data.
<template if:true={showTextPrompt}>
<p>This is a text Prompt</p>
</template>
<c-child-component onshowprompt={enablePrompt}>
showTextPrompt = false

enablePrompt(event) {
// set a template to true or something on the parent
this.showTextPrompt = true;
}
  • Another noteworthy point here is to understand the detail. The detail can have a single string data passed to it as:
const customEvent = new CustomEvent('sendtoparent', {
detail: 'Hello from Child!'
});


// And will be captured in the parent component later as :

this.messageFromChild = event.detail;

Or the detail can pass an object form of data as in earlier example like

const customEvent = new CustomEvent('sendtoparent', {
            detail: { message: 'Hello from Child!' }
        });

// And later be captured and treated like below:

this.messageFromChild = event.detail.message;

4. Why Events Over Direct Data Binding?

Child components should remain decoupled from their parents, meaning they should only communicate via events, rather than directly accessing or modifying the parent’s state. This keeps the code more maintainable and reusable.

By using events, the child component doesn’t care what the parent does with the data—it simply dispatches the event and continues with its own logic.

5. Event Propagation in LWC

After an event is fired by a component, it propagates up through the DOM of that component. To understand where events can be handled, we should also learn about how they propagate in the first place.

Events bubble up through the DOM structure; while the properties/attributes go down; that’s how the children and parents communicate in LWC. When we create an event in LWC, we can define the event propagation behavior based on two properties on the event, bubbles and composed.

Bubbling Phase Properties

  • Event.bubbles is a boolean value indicating whether the event can bubble up through the DOM or not. The default value is set to false.

In some cases, we want an event to bubble up to the multiple levels in the component hierarchy. This can be achieved by setting the bubbles property of the event to true. What it essentially means is that we can now communicate upwards in the hierarchy as well.

Example

const customEvent = new CustomEvent('sendtoparent', {
detail: { message: 'Hello from Child!' },
bubbles: true
});

When an event bubbles, it can be handled not only by the direct parent but by any component up the hierarchy that is listening for the event. This is useful in more complex component structures interfacing each other.

  • Event.composed is also a boolean value indicating whether the event can pass through the shadow boundary. The default value is set to false.

Each component’s internal DOM is encapsulated in a shadow DOM. The shadow boundary is the line between the regular DOM (also called the light DOM) and the shadow DOM. Look at the amazing structure below to understand it better.

Event Propagation in LWC
Event Propagation in LWC

So when we say bubbles is set to false, the event doesn’t bubble up through the DOM. And when we say composed is set to false, doesn’t cross the shadow boundary (apart from its own shadow boundary). The only way to listen to this event is to add an event listener directly on the component that dispatches the event, i.e. the event bubbles up to c-child only.

<c-child oneventname={method}></c-child>

We can read more about the event configuration in LWC here.

Final Thoughts

Congratulations! We have just mastered the Child-to-Parent communication in Lightning Web Components (LWC) using custom events for building dynamic Salesforce applications with a clean, maintainable component structure. Lets experiment more of these with more complex use cases. If you haven’t checked parent to child communication in LWC yet, well you should definitely read this lesson!

We also checkout other modes of communication in upcoming lessons like sibling to sibling communication in LWC, as well as Publish Subscribe model in LWC.

In the meantime if you have any questions or run into any issues, don’t hesitate to reach out! Shoot your queries below or resolve any for me. You can also checkout the forum at the home 🙌

Leave a Reply

error: Content is protected !!