GrandParent To GrandChild Communication

HINA SAYYAD
3 min readMar 8, 2024

In this blog, we’ll explore the fascinating interplay between grandparents and grandchildren in the context of Lightning Web Components (LWC), unraveling the intricacies of event propagation.

The Logic

Four components:

1. Grandparent component contains a button and a Parent component inside it which sends data to the grandchild with a button click.
2. Parent component contains a Child component inside it.
3. The child component contains a Grandchild component inside it.
4. Grandchild component contains a button that sends data to
the grandparent component with a button click.

This can be achieved through Event Propagation.

bubbles (default: false):

  • If set to true, the event will bubble up through the DOM hierarchy. This means that after the event is dispatched to a specific target, it will also trigger event listeners on its ancestors.
  • If set to false (default), the event will only be handled by the target and won't bubble up.

composed (default: false):

  • If set to true, the event will cross the boundary between the Shadow DOM and the regular DOM. In the context of web components, when a component uses Shadow DOM to encapsulate its styles and structure, events triggered inside the Shadow DOM won't typically propagate outside of it.
  • If set to false (default), the event will not cross the Shadow DOM boundary.

Here, I’ll provide an example of communication between a grandparent component and a grandchild component using Event Propagation.

<!-- GrandParentCmp.html -->

<template>
<lightning-card title="Grand Parent Component">
<div class="box slds-box slds-var-m-around_large">
This is <strong>Grand Parent</strong> Component
<div>
<lightning-input label="Enter Text" onchange={handleChange} value={dataTosend} class="slds-m-bottom_x-small"></lightning-input>
<lightning-button label="GrandParent" onclick={handleGrandParentSubmit}></lightning-button>
</div>
<div><strong>Message Sent: </strong>{messageSend}</div>
<div><strong>Message Received: </strong>{messageReceived}</div>
<c-parent-cmp
onparentevent={handleParentEvent}
onchildevent={handleChildEvent}
ongrandchildevent={handlegrandChildEvent}
message-received={messageSend}
></c-parent-cmp>
</div>
<br />
</lightning-card>
</template>
// GrandParentCmp.js

import { LightningElement } from "lwc";

export default class GrandParentCmp extends LightningElement {
messageReceived;
messageSend;
dataTosend ='';

handleChange(event){
this.dataTosend = event.target.value;
}

handleGrandParentSubmit() {
this.messageSend = this.dataTosend;
}

handleParentEvent(event) {
this.messageReceived = event.detail;
}

handleChildEvent(event) {
this.messageReceived = event.detail;
}

handlegrandChildEvent(event) {
this.messageReceived = event.detail;
}
}
<!-- parentCmp.html -->
<template>
<lightning-card title="Parent Component">
<div class="slds-box slds-var-m-around_large">
This is <strong>Parent</strong> Component
<div><strong>Message Received: </strong>{messageReceived}</div>
<div>
<c-child-cmp onchildevent={handleChildEvent} ongrandchildevent={handlegrandChildEvent} message-received={messageReceived}></c-child-cmp>
</div>
</div>
<br />
</lightning-card>

<!-- Child -->

</template>
//ParentCmp.js
import { api, LightningElement } from "lwc";

export default class ParentCmp extends LightningElement {
@api messageReceived;
messageSend;

handleParentSubmit() {
this.messageSend = "Hello";
this.dispatchEvent(
new CustomEvent("parentevent", {
detail: this.messageSend,
bubbles: true,
composed: true
})
);
}

handleChildEvent(event) {
this.messageReceived = event.detail;
console.log('20',this.messageReceived);
}

handlegrandChildEvent(event) {
this.messageReceived = event.detail;
console.log('24',this.messageReceived);
}
}
<!-- childCmp.html -->
<template>
<lightning-card title="Child Component">
<div class="slds-box slds-var-m-around_large">
This is <strong>Child</strong> Component
<div><strong>Message Received: </strong>{messageReceived}</div>
<div>
<c-grand-child-cmp ongrandchildevent={handlegrandChildEvent} message-received={messageReceived} ></c-grand-child-cmp>
</div>
</div>
<br />
</lightning-card>
</template>
// childCmp.js
import { api, LightningElement } from "lwc";

export default class childCmp extends LightningElement {
@api messageReceived;
messageSend;

handleChildSubmit() {
this.messageSend = "Hello";
this.dispatchEvent(
new CustomEvent("childevent", {
detail: this.messageSend,
bubbles: true,
composed: true
})
);
}

handlegrandChildEvent(event) {
this.messageReceived = event.detail;
}
}
<!-- grandChild.html -->
<template>
<lightning-card title="Grand Child Component">
<div class="slds-box slds-var-m-around_large">
This is <strong>Child</strong> Component
<div>
<lightning-input label="Enter Text" onchange={handleChange} class="slds-m-bottom_x-small" data-id="reset"></lightning-input>

<lightning-button label="Grand Child" onclick={handleGrandChildSubmit}></lightning-button>
</div>
<div><strong>Message Sent: </strong>{messageSend}</div>
<div><strong>Message Received: </strong>{messageReceived}</div>
</div>
<br />
</lightning-card>
</template>
//GrandChildCmp.js
import { api, LightningElement } from "lwc";

export default class GrandChildCmp extends LightningElement {
@api messageReceived;
messageSend;
dataTosend='';

handleChange(event){
this.dataTosend = event.target.value;
}

handleGrandChildSubmit() {
this.messageSend = this.dataTosend;
this.dispatchEvent(
new CustomEvent("grandchildevent", {
detail: this.messageSend,
bubbles: true,
composed: true
})
)

This demonstration showcases how custom events and event propagation seamlessly link the grandparent and grandchild components, facilitating a robust exchange of data.

--

--

HINA SAYYAD
HINA SAYYAD

Written by HINA SAYYAD

A vibrant mind with great personality.Always opine enigmatic thought about everything. Like to write about technology and lifestyle.

Responses (1)