Mastering Lightning Web Components: Passing Data from Parent to Child Components in LWC

Mastering Lightning Web Components: Passing Data from Parent to Child Components in LWC

March 30, 2023

LWC Parent to Child Communication

We’ll go over the most important ways for components in Salesforce’s Lightning Web Component (LWC) framework to talk to each other. LWC is the modern user interface framework for Salesforce. It is built on web standards and is meant to give users the best performance and most interesting experience. Understanding how to pass data between components is one of the most important parts of using LWC to build scalable, easy-to-maintain applications.This is not only makes it easier to reuse, but it also makes modular architecture more likely.

In this blog post, we’ll look at how to pass data from a parent component to a child component in LWC. This is an important idea to understand because it lets you build complex apps with lots of features while keeping your codebase clean and well-organized. We will go over the basic ideas, like how to use the @api decorator, bind properties in the parent component, and handle changes in the child component. We will also give a real-world example of how to use this technique in a Salesforce application.

By the end of this post, you’ll know exactly how to pass data from parent to child components in LWC. This will make it easy for you to make applications that are more flexible and modular. So, let’s jump right in

Parent component: myParent.html

<template>
<lightning-card title="Parent Component">
<lightning-input label="Enter a message" value={message} onchange={handleMessageChange}></lightning-input>
<c-my-child message-from-parent={message}></c-my-child>
</lightning-card>
</template>

Parent component: myParent.js

import { LightningElement, track } from 'lwc';

export default class MyParent extends LightningElement {
@track message = '';

handleMessageChange(event) {
this.message = event.target.value;
}
}

Child component: myChild.html

<template>
<lightning-card title="Child Component">
<p>Message from parent: {messageFromParent}</p>
</lightning-card>
</template>

Child component: myChild.js

import { LightningElement, api } from 'lwc';

export default class MyChild extends LightningElement {
@api messageFromParent;
}

As shown code above, the parent component (myParent) has an input field for the user to enter a message. When the input value changes, the handleMessageChange method is triggered, updating the message property. This property is then passed to the child component (myChild) using the message-from-parent attribute, which maps to the messageFromParent public property in myChild. js decorated with @api. The child component (myChild) then displays the message from the parent in its template.

Lets look into another example 

Here, we have a parent component that provides a list of accounts and a child component that provides information about a single account.
The selected account’s ID will be sent down from the parent component to the child component, which will use the ID to retrieve the account’s data and show it to the user.

Parent component: accountList.html

<template>
<lightning-card title="Account List">
<lightning-datatable
key-field="Id"
data={accounts}
columns={columns}
onrowselection={handleRowSelection}>
</lightning-datatable>
<c-account-details account-id={selectedAccountId}></c-account-details>
</lightning-card>
</template>

Parent component: accountList.js

import { LightningElement, track } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';

const columns = [
{ label: 'Account Name', fieldName: 'Name', type: 'text' },
{ label: 'Industry', fieldName: 'Industry', type: 'text' },
{ label: 'Phone', fieldName: 'Phone', type: 'phone' },
];

export default class AccountList extends LightningElement {
@track accounts;
@track columns = columns;
@track selectedAccountId;

connectedCallback() {
this.fetchAccounts();
}

async fetchAccounts() {
this.accounts = await getAccounts();
}

handleRowSelection(event) {
const selectedRows = event.detail.selectedRows;
if (selectedRows.length > 0) {
this.selectedAccountId = selectedRows[0].Id;
} else {
this.selectedAccountId = null;
}
}
}

Child component: accountDetails.html

<template>
<template lwc:if={account}>
<lightning-card title="Account Details">
<div class="slds-p-around_medium">
<p><b>Name:</b> {account.Name}</p>
<p><b>Industry:</b> {account.Industry}</p>
<p><b>Phone:</b> {account.Phone}</p>
<p><b>Website:</b> {account.Website}</p>
</div>
</lightning-card>
</template>
</template>

Child component: accountDetails.js

import { LightningElement, api, track } from 'lwc';
import getAccountDetails from '@salesforce/apex/AccountController.getAccountDetails';

export default class AccountDetails extends LightningElement {
@track account;
_accountId;

@api
get accountId() {
return this._accountId;
}

set accountId(value) {
this._accountId = value;
this.fetchAccountDetails();
}

async fetchAccountDetails() {
if (this._accountId) {
this.account = await getAccountDetails({ accountId: this._accountId });
} else {
this.account = null;
}
}
}

Apex Controller: AccountController.cls

public with sharing class AccountController {
@AuraEnabled(cacheable=true)
public static List<Account> getAccounts() {
// Example purpose extracting only 10 accounts, you can add required where clause
return [SELECT Id, Name, Industry, Phone FROM Account LIMIT 10];
}

@AuraEnabled(cacheable=true)
public static Account getAccountDetails(Id accountId) {
return [SELECT Id, Name, Industry, Phone, Website FROM Account WHERE Id = :accountId];
}
}

In above example, the parent component (accountList) fetches a list of accounts and displays them in a data table.

When a user selects a row in the account list, the handleRowSelection method is triggered. This method sets the selectedAccountId property to the ID of the selected account. The selectedAccountId property is then passed to the child component (accountDetails) using the account-id attribute.

A private property _accountId to store the account ID. We have also implemented a getter and setter for the public accountId property. Whenever the accountId property changes, the setter is called, which updates the _accountId private property and triggers the fetchAccountDetails method to fetch the account details for the new account ID.

This use case demonstrates how a parent Lightning Web Component can pass data (in this case, an account ID) to a child component, which then uses that data to perform some operation (fetching and displaying account details).


LWC Parent to Child Communication

LWC Parent to Child Communication

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Subscribe to our newsletter now!

    >