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.

Parent-to-child communication diagram showing augmentor-to-numerator.

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.

  1. Expose a public property in the child component (numerator):
    1. In Visual Studio Code, open numerator.js and apply the @api decorator to the counter property:
        @api counter = 0;
    2. Import the api decorator from the lwc module.
    3. Save the file.

  2. Create and code a new parent component named augmentor:
    1. Create a Lightning web component named augmentor.
    2. In augmentor.js, paste this code inside the Augmentor class:
        startCounter = 0;
        handleStartChange(event) {
          this.startCounter = parseInt(event.target.value);
        }
    3. Save the file.
    4. 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>
    5. Save the file.
    6. Update augmentor.js-meta.xml to make the augmentor component available on Lightning app pages:
          <isExposed>true</isExposed>
          <targets>
            <target>lightning__AppPage</target>
          </targets>
    7. Save the file.

  3. Add the new component (augmentor) to the Event Comms app page:
    1. Deploy the lwc folder and then refresh the Event Comms app page.
    2. Open the Event Comms app page for editing.
    3. Drag the augmentor component to the center region of the page.
    4. Click Save and then exit Lightning App Builder.

  4. Verify communications:
    1. To see the changes in Salesforce, refresh the Event Comms app page.
    2. Enter a number in the Set Starting Counter field.
      The count updates to what you entered.
    3. Click one of the multiply buttons.
      Notice that the counter updates but the Set Starting Counter stays the same.
    4. Change values in the original numerator component.
      It continues to work as expected.

The parent component (augmentor) sends information (startCounter) to the counter property in the child component (numerator).

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.

  1. Create a public function in the child component (numerator):
    1. Open numerator.js and add this maximizeCounter function after the handleMultiply function:
        @api
        maximizeCounter() {
          this.counter += 1000000;
        }
    2. Save the file.

  2. In the parent component (augmentor), add a button and its handler:
    1. Open augmentor.js and add this handleMaximizeCounter function after the handleStartChange function:
        handleMaximizeCounter() {
          this.template.querySelector('c-numerator').maximizeCounter();
        }
      This function finds the c-numerator tag in augmentor.html and calls the public maximizeCounter function.
    2. Save the file.
    3. Open augmentor.html and add this lightning-button after the Set Starting Counter lightning-input:
              <lightning-button 
                class="slds-var-p-vertical_xx-small"
                label="Add 1m To Counter"
                onclick={handleMaximizeCounter}>
              </lightning-button>
    4. Save the file.

  3. Verify communications:
    1. To see the changes in Salesforce, deploy the lwc folder and then refresh the Event Comms app page.
    2. 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.

Diagram corresponding to the preceding description.

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.

  1. Add a prior count to the child component (numerator):
    1. 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>
    2. Save the file.
    3. Open numerator.js and make @api counter = 0; a comment (add // to the beginning of the line).
    4. After the comment, add this code:
        _currentCount = 0;
        priorCount = 0;
        @api
        get counter() {
          return this._currentCount;
        }
        set counter(value) {
          this.priorCount = this._currentCount;
          this._currentCount = value;
        }
      This code changes counter to a property with getter (get) and setter (set) functions. It also adds the priorCount and _currentCount properties.
    5. Save the file.

  2. Verify communications:
    1. To see the changes in Salesforce, deploy the lwc folder and then refresh the Event Comms app page.
    2. Click Add, X2, and Add 1m To Counter to change the counter value.
      The Prior Counter stays in sync as you update the counter.
    3. 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.

Diagram corresponding to the preceding description.

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