Skip to main content

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

In plain words: In Salesforce Lightning Web Components (LWC), parent-to-child communication allows a parent container component to pass data, properties, or invoke methods down into its nested child components. This is primarily achieved by exposing public properties using the @api decorator.

Building modular, maintainable applications in Salesforce requires clear boundaries and predictable data flows between components. While child components communicate upward using custom events, parent components pass data downward into children using public properties and methods. Mastering parent-to-child communication patterns is a foundational skill for any Salesforce frontend developer.

1. Understanding the Parent-Child Relationship

In LWC architecture, a parent component encapsulates one or more child components within its HTML template. Data flows strictly in a downward direction: the parent owns the master state and distributes data down to its children.

  • Encapsulation: Child components reside inside the parent container, maintaining independent templates while accepting external input.
  • Public Properties (@api): The primary mechanism for exposing internal child variables so that parents can assign values to them directly.
360 Parent-to-Child Communication Card:
  • Decorator: Use import { api } from 'lwc' and annotate child properties with @api propertyName;.
  • Markup Binding: Pass values from parent to child templates using kebab-case attribute syntax (e.g., camelCase headerTitle becomes header-title in HTML).
  • Public Methods: Use @api on child functions to allow parents to invoke operations directly on the child instance.
  • Reactivity: Properties decorated with @api are reactive; when the parent updates the attribute value, the child component re-renders automatically.

2. Step-by-Step Implementation: Passing Data Downward

Step 1: Exposing a Public Property in the Child Component
The child component defines a public property decorated with @api.
// childComponent.js
import { LightningElement, api } from 'lwc';

export default class ChildComponent extends LightningElement {
    // Expose property publicly to parent components
    @api itemName = 'Default Item';
    @api itemPrice = 0.00;
}
<!-- childComponent.html -->
<template>
    <div class="slds-box slds-theme_shade">
        <p>Item Name: <strong>{itemName}</strong></p>
        <p>Price: <strong>${itemPrice}</strong></p>
    </div>
</template>
Step 2: Passing Values from the Parent Component
The parent component assigns values to the child's public attributes inside its HTML template. Note that camelCase JavaScript properties map to kebab-case HTML attributes.
<!-- parentComponent.html -->
<template>
    <lightning-card title="Parent Container" class="slds-m-around_medium">
        <div class="slds-p-around_medium">
            <!-- Pass parent state down to child component attributes -->
            <c-child-component 
                item-name={selectedProductName} 
                item-price={selectedProductPrice}>
            </c-child-component>
        </div>
    </lightning-card>
</template>
// parentComponent.js
import { LightningElement, track } from 'lwc';

export default class ParentComponent extends LightningElement {
    @track selectedProductName = 'Salesforce Enterprise License';
    @track selectedProductPrice = 150.00;
}

3. Invoking Public Child Methods from a Parent

In advanced scenarios, parents may need to trigger imperative actions inside a child component (such as clearing a form or refreshing data). This is accomplished by decorating a child method with @api and calling it via this.template.querySelector() from the parent.

// childComponent.js (Exposing a public method)
import { LightningElement, api } from 'lwc';

export default class ChildComponent extends LightningElement {
    @api resetComponentState() {
        // Perform reset logic inside child
        this.itemName = '';
        this.itemPrice = 0;
    }
}
// parentComponent.js (Invoking the child method)
export default class ParentComponent extends LightningElement {
    handleTriggerReset() {
        const childComponent = this.template.querySelector('c-child-component');
        if (childComponent) {
            childComponent.resetComponentState();
        }
    }
}

4. Common Traps & Best Practices

Developer Trap: Directly Mutating @api Properties in Child Components
Public properties passed from a parent are read-only from the child's perspective. Attempting to directly assign a new value to an @api property inside the child component controller violates LWC data flow principles and triggers runtime errors. If a child needs to modify data, it should dispatch a custom event upward to the parent.
Core Rule: Data flows downward in LWC. Use @api properties to pass state from parent to child, and dispatch custom events upward when children need to report user modifications.
  • Use Kebab-Case in HTML Templates: Remember that camelCase JavaScript properties (e.g., recordId) must be referenced in kebab-case within HTML markup (e.g., record-id).
  • Validate Property Inputs: Use getters and setters on @api properties in the child component if you need to validate or transform incoming data before rendering.
  • Keep Components Modular: Only pass necessary primitives or state objects down to children to maintain clear separation of concerns.

Summary

Parent-to-child communication is an essential pillar of Salesforce LWC architecture. By utilizing public @api properties, mapping camelCase properties to kebab-case HTML attributes, and leveraging public methods when imperative triggers are required, developers can build structured, responsive, and maintainable Salesforce applications.