In LWC, there are three different ways for components to communicate with each other:
Parent-to-child communication: A parent component can pass data and properties down to its child components. This is typically done using property bindings or custom events. For example:
// Parent component:
<template>
<c-child my-property={myData}></c-child>
</template>
// Child component:
<template>
<p>{myProperty}</p>
</template>
//child controller
@api myProperty
In this example, the Parent
component passes data down to its Child
component using a property binding (my-property={myData}
). The child component can then access the data using the @api
decorator.
Child-to-parent communication: A child component can send events to its parent component. This is typically done using custom events. For example:
// Child component:
<template>
<button onclick={handleClick}>Click me</button>
</template>
// Child component controller:
handleClick() {
const event = new CustomEvent('myevent', {
detail: { myData: 'Hello World' },
});
this.dispatchEvent(event);
}
// Parent component:
<template>
<c-child onmyevent={handleEvent}></c-child>
</template>
// Parent component controller:
handleEvent(event) {
console.log(event.detail.myData);
}
In this example, the Child
component sends a custom event (myevent
) to its parent component (Parent
) when the button is clicked. The parent component is listening for this event using the onmyevent
syntax, and can then access the data sent by the child component in the event detail.
Unrelated component communication: Unrelated components (i.e. components that are not in the same hierarchy) can communicate using the lightning/messageService
library. For example:
//Lightning message channel
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Description for your message channel</description>
<isExposed>true</isExposed>
<lightningMessageFields>
<description>Description of field</description>
<fieldName>data</fieldName>
</lightningMessageFields>
<masterLabel>messagechannel</masterLabel>
</LightningMessageChannel>
// Component A:
import { LightningElement } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import MESSAGE_CHANNEL from '@salesforce/messageChannel/messagechannel__c';
export default class ComponentA extends LightningElement {
@wire(MessageContext)
messageContext;
handleClick() {
const message = {
data: { message: 'Hello from Component A!' }
};
publish(this.messageContext, MESSAGE_CHANNEL, message);
}
}
// Component B:
import { LightningElement, wire } from 'lwc';
import { subscribe, MessageContext } from 'lightning/messageService';
import MESSAGE_CHANNEL from '@salesforce/messageChannel/messagechannel__c';
export default class ComponentB extends LightningElement {
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscription = subscribe(
this.messageContext,
MESSAGE_CHANNEL,
(message) => {
console.log(message.data.message); // Output: Hello from Component A!
}
);
}
disconnectedCallback() {
unsubscribe(this.subscription);
}
}
In this example, ComponentA
publishes a message to the messagechannel
channel using lightning/messageService
with a payload of { message: 'Hello from Component A!' }
. ComponentB
is subscribed to the same channel and listens for incoming messages using the same service. When the message is received, the payload is logged to the console.
In conclusion, component communication in LWC is an essential aspect of developing reusable and modular components. By leveraging the power of events and properties, LWC provides a flexible and intuitive way to pass data between components.