Communicate from Parent to Child
To enable communication from a parent component to a child component, the child exposes a property or function to make it public. Then the parent can update the child's public property or call the child's public function.
Additionally, if you want to add some functionality, update the public property to a getter and setter on the child component.
Let's start with a simple public property update. Another business unit found the Numerator you built. They want to use it and add to it. Their first request is to be able to set the starting number of the counter. We don't want to make any changes that will affect the original business use case, so let's wrap the numerator component in another component, which will hold the new functionality.Â
Update a Public Property
The @api
decorator in the child component exposes a property, making it public, so that the parent component can update it.
- Expose a public property in the child component (numerator):
- In Visual Studio Code, open numerator.js and apply the
@api
decorator to thecounter
property:@api counter = 0;
- Import the
api
decorator from thelwc
module.
- Save the file.
- Create and code a new parent component named
augmentor
:
- Create a Lightning web component named
augmentor
.
- In augmentor.js, paste this code inside the
Augmentor
class:startCounter = 0; handleStartChange(event) { this.startCounter = parseInt(event.target.value); }
- Save the file.
- Open augmentor.html and add this code between the
template
tags:<lightning-card title="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="1000000" value={startCounter} onchange={handleStartChange}> </lightning-input> </lightning-layout-item> </lightning-layout> <c-numerator class="slds-show slds-is-relative" counter={startCounter}> </c-numerator> </lightning-card>
- Save the file.
- Update augmentor.js-meta.xml to make the augmentor component available on Lightning app pages:
<isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> </targets>
- Save the file.
- Add the new component (augmentor) to the Event Comms app page:
- Deploy the lwc folder and then refresh the Event Comms app page.
- Open the Event Comms app page for editing.
- Drag the augmentor component to the center region of the page.
- Click Save and then exit Lightning App Builder.
- Verify communications:
- To see the changes in Salesforce, refresh the Event Comms app page.
- Enter a number in the Set Starting Counter field.
The count updates to what you entered.
- Click one of the multiply buttons.
Notice that the counter updates but the Set Starting Counter stays the same.
- Change values in the original numerator component.
It continues to work as expected.
Because we put Set Starting Counter in its own component (augmentor), instead of adding it to the numerator component, numerator continues to serve the original business case. Now numerator receives input from both its child (controls) and its parent (augmentor).
Call a Public Function
The second request from the business is to bump the count by one million. They don't want the Set Starting Count to change. This means we can't just update the startCounter property. We also don't have the current count in the augmentor component to add to. We'll call a public function on the child to do the update for us.
The @api
decorator in the child component exposes a function, making it public, so that the parent component can call it.
- Create a public function in the child component (numerator):
- Open numerator.js and add this
maximizeCounter
function after thehandleMultiply
function:@api maximizeCounter() { this.counter += 1000000; }
- Save the file.
- In the parent component (augmentor), add a button and its handler:
- Open augmentor.js and add this
handleMaximizeCounter
function after thehandleStartChange
function:This function finds thehandleMaximizeCounter() { this.template.querySelector('c-numerator').maximizeCounter(); }
c-numerator
tag in augmentor.html and calls the publicmaximizeCounter
function.
- Save the file.
- Open augmentor.html and add this
lightning-button
after the Set Starting Counterlightning-input
:<lightning-button class="slds-var-p-vertical_xx-small" label="Add 1m To Counter" onclick={handleMaximizeCounter}> </lightning-button>
- Save the file.
- Verify communications:
- To see the changes in Salesforce, deploy the lwc folder and then refresh the Event Comms app page.
- Click Add 1m To Counter.
The count is increased by one million.
In the parent (augmentor), the new button triggers the handleMaximizeCounter
handler, which calls the child component (numerator) and triggers its public maximizeCounter
function.
Use a Public Getter and Setter
This exercise is very similar to how you updated a property at the beginning of this step. In fact, we won't change the parent component at all. In the child component, we just implement the public counter property with a public getter and setter.
Both of the business units using Event Comms are loving the updates. Now they'd like to see the prior value of the count as the count changes. We need a way to capture the current count every time we change the counter property. We can get the current count and save it before we set the new value. Let's use a new private variable called _currentCount
so we can work with it. To hold the prior count so we can display it, we'll use a variable called priorCount
.
For the additional functionality, we implement the counter
property as a getter and setter (get
and set
, also known as an accessor property). Then every time the counter is set, we store the current counter value (_currentCount
) in the priorCount
variable before setting the new counter value.
- Add a prior count to the child component (numerator):
- Open numerator.html and add this paragraph just before the paragraph with the Count:
<p class="slds-text-align_center slds-var-m-vertical_medium"> Prior Count: <lightning-formatted-number value={priorCount}></lightning-formatted-number> </p>
- Save the file.
- Open numerator.js and make
@api counter = 0;
a comment (add//
to the beginning of the line).
- After the comment, add this code:This code changes
_currentCount = 0; priorCount = 0; @api get counter() { return this._currentCount; } set counter(value) { this.priorCount = this._currentCount; this._currentCount = value; }
counter
to a property with getter (get
) and setter (set
) functions. It also adds thepriorCount
and_currentCount
properties.
- Save the file.
- Verify communications:
- To see the changes in Salesforce, deploy the lwc folder and then refresh the Event Comms app page.
- Click Add, X2, and Add 1m To Counter to change the counter value.
The Prior Counter stays in sync as you update the counter.
- Click buttons in the Numerator and Augmentor components to see that the original functionality isn't affected.
We updated the numerator component to use a getter and setter to update the new priorCount
property. The parent component (augmentor) still sends information (startCounter
) to the child component (numerator). But now, the numerator uses a getter and setter to get
the _currentCount
property and set
the _currentCount
and priorCount
properties.
Challenge Yourself (optional—we won't check this code)
Update handleMaximizeCounter
and maximizeCounter
to accept an argument that specifies the number to add to the count. Hint: Review what you did in step 1 to send a data-factor
with the multiply
custom event.
Summary
You've tackled both child-to-parent and parent-to-child communication between Lightning web components. In the next step, you use the Lightning message service to communicate between components that don't have a parent-child relationship.
Resources
- YouTube: Lightning Web Components: Parent-Child Components
- Lightning Web Components Dev Guide: Create and Dispatch Events
- GitHub: LWC Recipes: apiProperty
- GitHub: LWC Recipes: apiSetterGetter
- Salesforce Developers Blog: Inter-Component Communication Patterns for Lightning Web Components