.
In Salesforce, you can establish communication between Lightning Web Components (LWCs) using various methods, depending on the relationship between the components and the specific use case. Here are some common ways to achieve communication between LWCs in Salesforce.
In this blog you'll learn:
1. Communicate from Child to Parent.
2. Communicate from Parent to Child.
Create a two-region Lightning app page named CommunicateComponents:
1. In Trailhead Playground open Setup.
2. In the Quick Find box, enter Lightning App Builder
and then select 'Lightning App Builder'.
3. Click New button.
4. With App Page selected, click Next.
5. To enter Label name, enter CommunicateComponents and then click Next.
6. Select Two Regions and then click Done.
7. Click on Save, Activate, Save, and Finish.
8. Click on back button Lightning App Builder.
1. Communicate from Child to Parent
Let's jump to the code:
First we will make parent component which is named parentNumerator
. In parentNumerator.html
file define tag for print counter value and called child component < c-childcontrols >< /c-childcontrols >
tag. In this tag we set two attribute onadd and onsubtract to perform parent component event. You can not set custom event name like ononadd and ononsubtract by using this event will not fire because inline event handler name must start with prefix "on" word. Which will do perform addition and subtractor operation. The parent component listens for the events and handles them. If you write like this <c-childcontrols ononadd={handleIncrement} ononsubtract={handleDecrement}>. Notice the doubled word onon, which is confusing.
parentNumerator.html<template> <div> <lightning-card title="Parent Numerator" icon-name="action:manage_perm_sets"> <p class="slds-text-align_center slds-var-m-vertical_medium"> Count: <lightning-formatted-number value={counter}></lightning-formatted-number> </p> <c-childcontrols onadd={handleIncrement} onsubtract={handleDecrement}></c-childcontrols> </lightning-card> </div> </template>
parentNumerator.jsimport { LightningElement } from 'lwc'; export default class ParentNumerator extends LightningElement { counter = 0; handleIncrement() { this.counter++; } handleDecrement() { this.counter--; } }
In parentNumerator.js-meta.xml we set true value between isExposed tag and targets lightning__AppPage
parentNumerator.js-meta.xml<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>58.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> </targets> </LightningComponentBundle>
Now we will do create child component which is named childcontrols. In this child component we have defined two button one for addition and another is for subtract operations. To perform addition and subtraction we have passed onclick event in both button. For additon event name is handleAdd and for subtraction event name is handleSubtract.
childcontrols.html<template> <lightning-card title="Child Controls" icon-name="action:upload"> <lightning-layout> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-button label="Add" onclick={handleAdd}></lightning-button> </lightning-layout-item> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-button label="Sub" onclick={handleSubtract}></lightning-button> </lightning-layout-item> </lightning-layout> </lightning-card> </template>
Now jump into the childcontrols.js file. In this javascript file have defined two event which does dispatch the event with custom event name add and subtract which is define in <c-childcontrols onadd={handleIncrement} onsubtract={handleDecrement}></c-childcontrols> tag in parentNumerator.html file. When user click on buttons, the component create and dispatch add and subtract events. Then parentNumerator component listens for the events and handles them. The listeners are onadd and onsubtract. When <c-childcontrols></c-childcontrols> tag receives the add and subtract events, handleIncrement() and handleDecrement() increase and decrease the counter value.
childcontrols.jsimport { LightningElement } from 'lwc'; export default class Childcontrols extends LightningElement { handleAdd() { this.dispatchEvent(new CustomEvent('add')) } handleSubtract() { this.dispatchEvent(new CustomEvent('subtract')) } }
childcontrols.js-meta.xml<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>58.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>
a) Pass data from the child to the parent:
Now this turn is passing a value from child component to parent component. To getting value from child components into parent compoents we have to difine detail property in parent component event. With event.detail property we can get value from child component.
parentNumerator.html<template> <div> <lightning-card title="Parent Numerator" icon-name="action:manage_perm_sets"> <p class="slds-text-align_center slds-var-m-vertical_medium"> Count: <lightning-formatted-number value={counter}></lightning-formatted-number> </p> <c-childcontrols onmultiply={handleMultiply}></c-childcontrols> </lightning-card> </div> </template>
parentNumerator.jsimport { LightningElement } from 'lwc'; export default class ParentNumerator extends LightningElement { counter = 1; handleMultiply(event) { const factor = event.detail; this.counter *= factor } }
To send value of child component we have define data-factor="2" in button one and data-factor="3" in another button which will handle by handleMultiply() event in child component
childcontrols.html<template> <lightning-card title="Child Controls" icon-name="action:upload"> <lightning-layout> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-button label="2" data-factor="2" icon-name="utility:close" onclick={handleMultiply}></lightning-button> </lightning-layout-item> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-button label="3" data-factor="3" icon-name="utility:close" onclick={handleMultiply}></lightning-button> </lightning-layout-item> </lightning-layout> </lightning-card> </template>
In this childcontrols.js file we have get data-factor attribute value through event.target.dataset.factor statement. Inside dispatch event we assign value of factor variable into detail property like below example.
childcontrols.jsimport { LightningElement } from 'lwc'; export default class Childcontrols extends LightningElement { handleMultiply(event) { const factor = event.target.dataset.factor; console.log('From Child ::'+ factor) this.dispatchEvent(new CustomEvent('multiply', { detail: factor })) } }
b) Allow custom events to bubble
Now we want to more multiply option for example we want to it multiply by 0, 1, 2, 3, 4 ....n so on. For do that we create another compoenent called button component. This button component we can replace of two buttons inside childcontrols.html components.
parentNumerator.html<template> <div> <lightning-card title="Parent Numerator" icon-name="action:manage_perm_sets"> <p class="slds-text-align_center slds-var-m-vertical_medium"> Count: <lightning-formatted-number value={counter}></lightning-formatted-number> </p> <c-childcontrols onmultiply={handleMultiply}></c-childcontrols> </lightning-card> </div> </template>
parentNumerator.jsimport { LightningElement } from 'lwc'; export default class ParentNumerator extends LightningElement { counter = 1; handleMultiply(event) { const factor = event.detail; this.counter *= factor } }
childcontrols.html<template> <lightning-card title="Child Controls" icon-name="action:upload"> <lightning-layout> <lightning-layout-item flexibility="auto" padding="around-small"> <template for:each={factors} for:item="factor"> <c-button key={factor} label={factor} data-factor={factor} icon="utility:close" onbuttonclick={handleMultiply}> </c-button> </template> </lightning-layout-item> </lightning-layout> </lightning-card> </template>
childcontrols.jsimport { LightningElement } from 'lwc'; export default class Childcontrols extends LightningElement { factors = [0,2,3,4,5,6]; handleMultiply(event) { const factor = event.target.dataset.factor; console.log('From Child ::'+ factor) this.dispatchEvent(new CustomEvent('multiply', { detail: factor })) } }
button.html<template> <lightning-button label={label} data-factor={label} icon-name={icon} onclick={handleButton}> </lightning-button> </template>
button.jsimport { LightningElement, api} from 'lwc'; export default class Button extends LightningElement { @api label @api icon handleButton(event){ const factor = event.target.dataset.factor console.log('From Button :'+ factor) this.dispatchEvent(new CustomEvent('buttonclick'), { // bubble true }) } }
button.js-meta.xml<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>58.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>
2. Communicate from Parent to Child
To done communication from parent to child components we have to create public property or function. After then parent component can update the child public property or call public function.
In parentagumentor.html file hava a button which will call child compoenent function maximizeCounter() through this.template.querySelector() method inside the handleMaximizeCounter().
parentaugmentor.html<template> <lightning-card title="Parent Augmentor" icon-name="action:download"> <lightning-layout> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-input label="Set Starting Counter" type="number" min="0" max="1000" value={startCounter} onchange={handleStartChange}> </lightning-input> </lightning-layout-item> </lightning-layout> <c-childnumerator class="slds-show slds-is-relative" childpropertycounter={startCounter}></c-childnumerator> <lightning-layout-item flexibility="auto" padding="around-small"> <lightning-button class="slds-var-p-vertical_xx-small" label="Add 10 To Counter" onclick={handleMaximizeCounter}> </lightning-button> </lightning-layout-item> </lightning-card> </template>
parentaugmentor.jsimport { LightningElement } from 'lwc'; export default class Parentaugmentor extends LightningElement { startCounter = 0; handleStartChange(event) { this.startCounter = parseInt(event.target.value); } handleMaximizeCounter() { this.template.querySelector('c-childnumerator').maximizeCounter(); } }
In parentagumentor.js-meta.xml we set true value between isExposed tag and targets lightning__AppPage
parentagumentor.js-meta.xml<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>58.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> </targets> </LightningComponentBundle>
childnumerator.html<template> <lightning-card title="Child Numerator" icon-name="action:manage_perm_sets"> <p class="slds-text-align_center slds-var-m-vertical_medium"> Count: <lightning-formatted-number value={childpropertycounter}></lightning-formatted-number> </p> </lightning-card> </template>
In this childnumerator.js file define childpropertycounter variable which is public property and maximizeCounter() method which is also public function. To make public property and method set @api decorator. Here maximizeCounter() funtion will increase value by 10 which will call from parentaugmentor component.
chidlnumerator.jsimport { LightningElement, api } from 'lwc'; export default class Childnumerator extends LightningElement { @api childpropertycounter = 0; @api maximizeCounter() { this.childpropertycounter += 10; } }
childnumerator.js-meta.xml<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>58.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>