@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.
- 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
headerTitlebecomesheader-titlein HTML). - Public Methods: Use
@apion child functions to allow parents to invoke operations directly on the child instance. - Reactivity: Properties decorated with
@apiare reactive; when the parent updates the attribute value, the child component re-renders automatically.
2. Step-by-Step Implementation: Passing Data Downward
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>
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
@api Properties in Child ComponentsPublic 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.
@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
@apiproperties 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.