Parent-child communication in Lightning Web Components is achieved through public properties decorated with @api. This enables a unidirectional data flow where parents control the state and behavior of their children.
The @api Decorator
The @api decorator makes a property or method public, allowing parent components to access it. Properties marked with @api are reactive, meaning changes automatically trigger a re-render of the component.
Importing @api
import { LightningElement , api } from 'lwc' ;
Public Properties
Public properties allow parent components to pass data to child components.
Child Component Definition
contactTile.js
import { LightningElement , api } from 'lwc' ;
export default class ContactTile extends LightningElement {
@ api contact ;
}
contactTile.html
< template >
< template lwc:if = {contact} >
< lightning-layout vertical-align = "center" >
< lightning-layout-item >
< img
lwc:if = {contact.Picture__c}
src = {contact.Picture__c}
alt = "Profile photo"
/>
< lightning-icon
lwc:else
icon-name = "standard:avatar"
alternative-text = "Missing profile photo"
></ lightning-icon >
</ lightning-layout-item >
< lightning-layout-item padding = "around-small" >
< p > {contact.Name} </ p >
< p > {contact.Title} </ p >
< p >
< lightning-formatted-phone
value = {contact.Phone}
></ lightning-formatted-phone >
</ p >
</ lightning-layout-item >
</ lightning-layout >
</ template >
< template lwc:else >
< p > No contact data available. </ p >
</ template >
</ template >
Parent Component Usage
compositionBasics.js
import { LightningElement } from 'lwc' ;
export default class CompositionParent extends LightningElement {
contact = {
Name: 'Amy Taylor' ,
Title: 'VP of Engineering' ,
Phone: '6172559632' ,
Picture__c:
'https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/amy_taylor.jpg'
};
}
compositionBasics.html
< template >
< c-contact-tile contact = {contact} ></ c-contact-tile >
</ template >
Multiple Public Properties
A child component can expose multiple public properties to accept different types of data.
Example: Multiple Properties
child.js
import { LightningElement , api } from 'lwc' ;
export default class Child extends LightningElement {
@ api firstName ;
@ api lastName ;
get fullName () {
return ` ${ this . firstName } ${ this . lastName } ` ;
}
}
child.html
< template >
< p > Hello, {fullName}! </ p >
</ template >
Parent usage:
< template >
< c-child first-name = "Jennifer" last-name = "Wu" ></ c-child >
</ template >
Property names in HTML use kebab-case (first-name), but the corresponding JavaScript property uses camelCase (firstName)
Property Binding
You can bind parent component properties to child component properties using curly braces {}.
Static Values
< c-child first-name = "Amy" last-name = "Taylor" ></ c-child >
Dynamic Values
< c-contact-tile contact = {contact} ></ c-contact-tile >
Complex Objects
You can pass entire objects, not just primitive values:
// Parent component
contact = {
Name: 'Amy Taylor' ,
Title: 'VP of Engineering' ,
Phone: '6172559632' ,
Picture__c: 'https://example.com/photo.jpg'
};
< c-contact-tile contact = {contact} ></ c-contact-tile >
Best Practices
Use descriptive property names
Choose clear, self-documenting names for your public properties @ api contact ; // Good
@ api data ; // Too generic
Validate input data
Check for null or undefined values in your child component < template lwc:if = {contact} >
<!-- Render contact -->
</ template >
< template lwc:else >
< p > No contact data available. </ p >
</ template >
Keep components focused
Each component should have a single, well-defined responsibility
Document public APIs
Use JSDoc comments to document what each public property expects /**
* @api
* @type {Object}
* @description Contact record with Name, Title, Phone, and Picture__c fields
*/
@ api contact ;
Data Flow Rules
Data flows down from parent to child. Child components should not modify properties received from parents. This ensures a predictable, unidirectional data flow.
Parent controls the data : The parent component owns and manages the state
Child receives the data : The child component receives data through @api properties
Child displays the data : The child component renders the data but doesn’t modify it
Child communicates changes : If the child needs to trigger changes, it dispatches events to the parent
Common Patterns
Passing Primitive Values
// Parent
export default class Parent extends LightningElement {
firstName = 'Amy' ;
lastName = 'Taylor' ;
}
<!-- Parent template -->
< c-child first-name = {firstName} last-name = {lastName} ></ c-child >
Passing Objects
// Parent
export default class Parent extends LightningElement {
contact = {
Name: 'Amy Taylor' ,
Title: 'VP of Engineering'
};
}
<!-- Parent template -->
< c-contact-tile contact = {contact} ></ c-contact-tile >
Passing Arrays
See the Nesting Patterns guide for examples of passing arrays and iterating over child components.
Next Steps
Nesting Patterns Learn about iterating over arrays to create multiple child instances
Events Discover how child components communicate back to parents