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

As we explore more on the Lightning Web Components, one of the key concepts to grasp here is Parent to Child Communication in Lightning Web Components (LWC). In Salesforce development, it’s expected to build complex applications where components interact with each other, especially when they have a parent-child relationship.

Parent to Child Communication in Lightning Web Components (LWC)

In this blog post, we will discuss the various ways to establish communication from parent components to child components in LWC. We will learn when to use each which of these implementations, and why it’s effective, and how it fits into the larger Salesforce architecture. Whether you’re new to LWC or you’re just refining your skills, this guide will help you master these communication patterns.

How to Implement Parent to Child Communication in LWC

Before diving into the specific techniques, let’s clarify what we mean by parent to child communication in LWC. In this context:

  • A parent component is a container or a higher-level component that may include one or more child components within its template.
  • A child component is a nested component inside a parent component and can accept data or invoke actions based on the parent’s behavior.

This type of communication is crucial when we want to pass data or control behavior of our LWC applications.

LWC Parent to Child Data Sharing

There are several ways to send data or messages from a parent component to a child component in LWC.

Parent to Child Communication in LWC

Each approach has its specific use cases, and we will take you through all of them:

  1. Using Public Properties : to pass primitive data from parent component to an exposed field/property in child component.
  2. Calling Public Methods in Child Components: to pass non-primitive data from parent component to an exposed method in a child component.
  3. Template Querying (template.querySelector): to call a child component method from a parent component querying template reference.
  4. Dynamic Data Binding : to reactively pass data to the child component via an action on the parent component.

Let’s take a deep dive into each of these patterns, but first understand @api decorator in LWC.

@api decorator in LWC

  • The @api decorator is used to make a field/property or a method public.
  • Making a method or field public means exposing the property to the parent component that uses the component in its HTML markup, can hereby access these public properties via HTML attributes.
  • Public properties are reactive in nature and if the value of the property changes, the component’s template re-renders.

Understanding communication between components in Salesforce LWC


1. Using Public Properties

The most common way for LWC parent to child data sharing is through public properties. Public properties are exposed in the child component using the @api decorator, allowing the parent to set values on the child from its own template.

How It Works

  • Parent: Calls a public method directly on the child component.
  • Child: Exposes a method with @api that the parent can invoke.

Here’s how we can implement it:

Step 1: Define Public Property in Child

In the child component, you define a public property with the @api decorator. This makes it accessible from the parent to the child component.

Example childComponent.js
import { LightningElement, api } from 'lwc';

export default class ChildComponent extends LightningElement {
@api messageFromParent;
@api isTrue
// This will hold the data passed by the parent
}
Example childComponent.html
<template>
{messageFromParent} {isTrue}
</template>

Step 2: Pass Data from Parent

In the parent component, you can pass data to this public property by referencing the child component in the HTML.

Example parentComponent.html
<template>
<c-child-component

message-from-parent="Hello, child component!"
is-true>
</c-child-component>
</template>

In this example, the parent component is passing the string "Hello, child component!" to the messageFromParent property in the child.

Readers Note:

  1. Defining an attribute and not initializing or assigning any value to it makes its value set as true.
  2. Attributes in camelCase are always converted into kebab-case on the parent HTML.
    messageFromParent==> message-from-parent

2. Calling Public Methods in Child Components

Another powerful way to communicate with child components is by calling methods that are publicly accessible in the child. Similar to public properties, public methods are also decorated with the @api decorator in the child component.

How It Works

  • Parent: Calls a public method directly on the child component.
  • Child: Exposes a method with @api that the parent can invoke.

Step 1: Define Public Method in Child

In the child component, define a method and decorate it with @api.

Example childComponent.js
import { LightningElement, api } from 'lwc';

export default class ChildComponent extends LightningElement {
@api carouselDetails
}
}

Step 2: Call the Method from Parent

In the parent component, we pass carouselData to the component similar to how we explained above.

Example parentComponent.html
<!-- parentComponent.html -->
<template>
<c-child-component
carousel-details={carouselData}>
</c-child-component>
</template>

In the parent’s JavaScript file, we have the carouselData method with the data.

Example parentComponent.js
import { LightningElement } from 'lwc';

export default class ParentComponent extends LightningElement {


carouselData=[       

{    src:"https://www.lightningdesignsystem.com/assets/images/carousel/carousel-01.jpg",
          header:"Card1"
}, 
     
{    src:"https://www.lightningdesignsystem.com/assets/images/carousel/carousel-02.jpg",
            header:"Card2"      
},    
{     src:"https://www.lightningdesignsystem.com/assets/images/carousel/carousel-03.jpg",
            header:"Card3"      
}   
]}

We receive the data in the child component in the js file using @api decorator, and the html thereby shows the data in its glory!

Example childComponent.html
<!-- childComponent.html -->
<template>
<lightning-carousel disable-auto-scroll>
<template for:each={carouselDetails} for:item="item">
<lightning-carousel-image
key={item.header}
src ={item.src}
header ={item.header}>
</lightning-carousel-image>
</template>
</lightning-carousel>
</template>
Example childComponent.js
import { LightningElement, api } from 'lwc';

export default class childComponent extends LightningElement { 
  @api carouselDetails
}

It is useful when we want the parent component to trigger specific actions in the child component, such as showing certain details, show an alert, reset a form, or perform logical operations.

3. Template Querying (template.querySelector)

Sometimes we may require the parent to manipulate the child’s DOM and call a specific child component elements. This is where template querying using template.querySelector() comes into play.

How It Works

  • Parent: Queries the DOM to find the child component or specific elements within the child.
  • Child: Exposes itself as part of the DOM for direct querying.

This approach is especially useful for accessing DOM elements within a child component, but it should be used sparingly to avoid tightly coupling components.

Example parentComponent.html

<!-- Calling child method from parent -->
<template>
<lightning-button variant="brand"
label="Reset Slider"
onclick={handleClick}>
</lightning-input>
<c-child-component></c-child-component>
</template>

Example parentComponent.js


import { LightningElement } from 'lwc';

export default class ParentComponent extends LightningElement {
handleClick() {
this.template.querySelector('c-child-component').resetSlider();
}
}

Here in this example we have a slider element on the child component with changes being reflected by changeHandler in childComponent.js . But the same slider can also be manipulated by data from parent component via resetSlider method (exposed by @api) in childComponent.js via handleClick (button action) on parentComponent.js .

Example childComponent.html

<template>
<lightning-slider label="Volume"
value={vol}
onchange={changeHandler}>
{message}
</template>

Example childComponent.js

import { LightningElement,api } from 'lwc';

export default class ChildComponent extends LightningElement {

vol = 20
changeHandler(event){
this.vol = event.target.value
}
@api resetSlider(){
this.vol = 50
}

}

Here, the parent component manipulates the vol value inside the child component’s DOM invoking the resetSlider method.

4. Dynamic Data Binding (Reactive changes)

While public properties are a great way to pass static values, we may need to handle reactive changes where the data from the parent changes and the child needs to respond immediately. LWC uses reactive data binding to automatically update components when the data they depend on changes.

How It Works

  • Parent: Binds data reactively to child component properties.
  • Child: Reactively updates(re-renders) its UI or logic based on the data.

This approach works similarly to public properties, but the child will automatically re-render when the parent’s data changes.

As the input is entered into the parent component’s input text, the input value is updated on the message property in the parentComponent.js. And as the message property is updated, it is passed down to the child component as it is bind to the child component attribute dynamicmessage.

Example parentComponent.html

<!-- parentComponent.html -->
<template>


<lightning-input type="text"
label="Enter some text"
onkeyup={updateMessage}
value={message}>
</lightning-input>

<c-child-component
dynamic-message={message}>
</c-child-component>

</template>

Example parentComponent.js

import { LightningElement } from 'lwc';

export default class ParentComponent extends LightningElement {


message = 'Initial message';

updateMessage(event) {
this.message = event.target.value
}
}

As the updated value is passed down, the dynamicMessage in childComponent.js will listen to the new value. The dynamicMessage is bound to the child’s property, and when it is updated, the child component will re-render with the new value on {dynamicMessage} in childComponent.html .

Example childComponent.html

<template>
{dynamicMessage}
</template>

Example childComponent.js

import { LightningElement,api } from 'lwc';

export default class ChildComponent extends LightningElement {
@api dynamicMessage

}

Readers Note: The onkeyup event occurs when the user releases a key on the keyboard. 


Conclusion

With this post now, I hope we should have built a solid understanding of the different approaches for parent-to-child communication in LWC:

Quick Summary

  • Public properties: Ideal for passing primitive values from parent to child.
  • Public methods: Useful for passing non primitive data like objects to the child component.
  • Template querying (querySelector): Allows the parent to directly access the child’s DOM.
  • Dynamic data binding: Reactively updates child components based on parent’s state.

Each of these techniques has its use case, depending on your our requirement. By mastering these communication patterns, we can enable ourselves to create more modular, maintainable, and interactive components in our Salesforce applications.

If you have any queries for me, please shoot a comment down below! Let me know if you still think a video lecture is better though I prefer handy written concepts I can read in my own calm.. Check out this too.

Leave a Reply

error: Content is protected !!