In Salesforce Lightning Web Components (LWC), Events establish connections between the components, such as sending messages from one component to another, triggering actions, and updating information.
With this, the events enable actions like button clicks, form submissions, or data updates. In this Salesforce tutorial, we will learn about events and how to handle events in Salesforce Lightning web components.
What are Events in Salesforce Lightning Web Components?
In Salesforce Lightning Web Components, events enable Lightning components to communicate with each other, allowing a component to send notifications to other components within the hierarchy.
To handle events in Lightning Web Components, we use the CustomEvent object to define and execute custom events within the LWC component and then refer to those events in the HTML template using the on attribute, allowing for declarative event handling between parent and child components or within the same component hierarchy.
There are typically three approaches for communication between the components using events.
- Parent-to-child event communication in Lightning web component.
- Custom Event Communication in Lightning Web Component (Child to Parent ).
- Publish Subscriber model in Lightning Web Component.
Parent-to-Child Event Communication in Lightning Web Component
For Parent-to-child event communication in the Lightning web component in Salesforce, we can pass the details from parent to child using two ways below:
- Public Method
- Public Properties
Parent-to-Child Event in LWC Through Public Method
In the Public method, we use the @api decorator to make the method publicly available so the parent component can call it directly using the JavaScript API.
Now, open the Salesforce developer console or VS Code Studio and follow the steps below.
1. First, we will create a child component with a template that will display the message from the parent component. For that, follow the code below in the HTML file.
<template>
Message from Parent: {message}
</template>2. After this, enter the code below in the JavaScript file to assign the value in the child component.
import { LightningElement, api } from 'lwc';
export default class ChildComponent extends LightningElement {
@api message;
}3. Now, create the Parent component to call the Child component. In this, we will pass data using a property in the parent component.
Enter the code below in the HTML file of the parent component.
<template>
<c-child-component message={parentMessage}></c-child-component>
</template>4. Now, we need to enter the code below in the JS file of the parent component.
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
parentMessage = 'Message from Parent Component';
}5. After creating the parent and the child components, change the XML file of both components to expose them to the lightning pages by using the code below inside the LightningComponentBundle tag.
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>6. After adding both components to the page layout, you will see input text in the parent, and whatever value we enter will reflect in the child component.

This way, we can handle parent-to-child events in LWC through the public method.
Parent-to-child event in LWC through Public Properties
In the LWC components, Parent-to-child communication can be achieved using public properties. This allows the parent component to pass data or trigger logic in the child component efficiently.
1. First, create a Child component and enter the code below in the JS file of the component.
import { LightningElement, api } from 'lwc';
export default class ChildComponent extends LightningElement {
@api message;
}2. In this example, we will display the message from the parent component, and for that, enter the below code in the HTML file of the child component.
<template>
<p>Message from Parent with properties: {message}</p>
</template>3. Create the Parent component and enter the code below in the HTML file, where the parent component sends the message attribute to the child component, which then shows it.
<template>
<lightning-input
label="Enter Message"
value={parentMessage}
onchange={handleChange}
></lightning-input>
<c-child-component message={parentMessage}></c-child-component>
</template>4. Enter the code below in the parent component JS file. In this, we allow the user to update the message dynamically using a text input field.
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
parentMessage = 'Hello, Child!';
handleChange(event) {
this.parentMessage = event.target.value;
}
}Initially, parentMessage has the text message “Hello, Child!“. When the user types something in the input, handleChange(event) updates parentMessage with the new input value because message={parentMessage} is related to the child component that automatically updates whenever parentMessage changes.
5. Make the changes in the XML files of both components and make them available for the lightning pages.
Using this method, we can handle Parent-child events in Salesforce LWC components via public properties.
Custom Event Communication in Salesforce LWC (Child to Parent)
In Salesforce LWC, we use the Custom Event object to establish communication from the child to the parent component through which we can create and dispatch a custom event.
Creating and Triggering an Event:
The CustomEvent() constructor is used to create an event. This constructor requires two main parameters: the name of the custom event and the event details (props). The syntax is as follows: new CustomEvent(eventName, props).
The EventTarget.dispatchEvent() method triggers or dispatches the event. This method dispatches the event to the target element using this.dispatchEvent(new CustomEvent(eventName, props)).
For the handling of an event, there are two primary methods to listen for an event: Declarative via HTML markup method and JavaScript using the addEventListener method.
Custom Event communication in LWC (Child to Parent) via Declarative markup HTML
Let’s take an example where the child component sends a list of products or items to the parent component.
1. First, we will create a child component to get the input values from the user, where the user will select the values from the picklist.
After creating the component, enter the code below in the HTML file.
<template>
<lightning-card title="Child Component - Product Selection">
<div class="slds-m-around_medium">
<lightning-combobox
name="productPicker"
label="Select a Product"
options={productOptions}
onchange={handleProductChange}>
</lightning-combobox>
</div>
</lightning-card>
</template>In this, we have defined a picklist combo box from which the user will select an option from the available picklist values. The onchange={handleProductChange} will trigger the handleProductChange function in JavaScript when the user selects a product.
2. Now, enter the code below in the JS file of the child component to define the logic for dispatching a custom event when a product is selected.
import { LightningElement } from 'lwc';
export default class ChildComponent extends LightningElement {
productOptions = [
{ label: 'Laptop', value: 'Laptop' },
{ label: 'Smartphone', value: 'Smartphone' },
{ label: 'Tablet', value: 'Tablet' },
{ label: 'Smartwatch', value: 'Smartwatch' }
];
handleProductChange(event) {
const selectedProduct = event.detail.value;
console.log('Selected Product:', selectedProduct);
const productEvent = new CustomEvent('productselected', {
detail: selectedProduct,
});
this.dispatchEvent(productEvent);
}
}In the above code logic, the handleProductChange(event) method extracts the selected product using event.detail.value and logs it for debugging.
It then dispatches a CustomEvent (productselected) with the selected product as the event detail.
Finally, this.dispatchEvent(productEvent) sends the event to the parent component.
3. After this, create the parent component and enter the code below in the HTML of the parent component that will display the selected product according to the event from the child component.
<template>
<div class="slds-m-around_medium">
<lightning-card title="Parent Component">
<p class="slds-m-around_medium">
Selected Product: <strong>{selectedProduct}</strong>
</p>
<c-child-component onproductselected={handleProductSelection}></c-child-component>
</lightning-card>
</div>
</template>4. Now, the code below in the JS file of the parent component will handle the event from the child component and display the selected product on the parent.
import { LightningElement, track } from 'lwc';
export default class ParentComponent extends LightningElement {
@track selectedProduct = 'None';
handleProductSelection(event) {
console.log('Product Selected in Parent:', event.detail);
this.selectedProduct = event.detail;
}
}5. After this, expose the child and the parent component to the lightning page with the code below inside the LightningComponentBundle tag of the XML file.
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>6. Now, deploy the component on the Lightning page and save the changes.
7. After deploying the component, when you select or change the product in the child component, it will reflect the changes in the parent component.

This way, we can establish custom event communication between two LWC components in a Child-to-parent relationship.
Custom Event communication in LWC (Child to Parent) using the addEventListener method
In the addEventListener method, we will attach the event listener specifically in JavaScript instead of using the declarative on<event> syntax in the HTML template.
The example for the Child-to-Parent event call is going to be the same as the previous one, where we selected the product values from the combo box, and the same was reflected in the Parent component.
1. We are using the above example, so we don’t need to change the code of the HTML file of the child component because the only change is in the parent component, where we add the event listener.
Now, make the changes in the JS file of the child component with the code below.
import { LightningElement } from 'lwc';
export default class ChildComponent extends LightningElement {
productOptions = [
{ label: 'Laptop', value: 'Laptop' },
{ label: 'Smartphone', value: 'Smartphone' },
{ label: 'Tablet', value: 'Tablet' },
{ label: 'Smartwatch', value: 'Smartwatch' }
];
handleProductChange(event) {
const selectedProduct = event.detail.value;
console.log('Selected Product:', selectedProduct);
const productEvent = new CustomEvent('productselected', {
detail: selectedProduct,
bubbles: true,
composed: true
});
this.dispatchEvent(productEvent);
}
}In the above logic, the child component dispatches the product’s selected event, which includes the selected product in its details. The event is sent using this.dispatchEvent(productEvent).
We also set bubbles as true, which means the component is enabled to bubble up through the DOM, which is, by default, set to ‘false.’ If the ‘composed‘ property is set to ‘true‘, it means the event is allowed to pass through the ‘shadow boundary,’ which is also set to ‘false‘ by default.
2. In the HTML of the parent component, enter the code below where we have removed the binding to select the product, unlike the previous method.
<template>
<div class="slds-m-around_medium">
<lightning-card title="Parent Component">
<p class="slds-m-around_medium">
Selected Product: <strong>{selectedProduct}</strong>
</p>
<c-child-component></c-child-component>
</lightning-card>
</div>
</template>3. In this step, we will programmatically define the event listener, and for that, we will use the addEventListener to listen for the product selected event from the child component.
import { LightningElement, track } from 'lwc';
export default class ParentComponent extends LightningElement {
@track selectedProduct = 'None';
renderedCallback() {
const childComponent = this.template.querySelector('c-child-component');
childComponent.addEventListener('productselected', this.handleProductSelection.bind(this));
}
disconnectedCallback() {
const childComponent = this.template.querySelector('c-child-component');
childComponent.removeEventListener('productselected', this.handleProductSelection.bind(this));
}
handleProductSelection(event) {
this.selectedProduct = event.detail;
}
}In the above method, we have used the renderedCallback() method, which is a lifecycle hook that is called after a component has finished rendering on the page, meaning all its HTML elements are visible in the browser.
For the reference of the child component, we have used this.template.querySelector(‘c-child-component’). After this, we used addEventListner to handle the productSelected event and bind the handleProductSelection method to the event.
The handleProductSelection(event) method is called when the productselected event is triggered. It receives the event and updates the product value in the parent component.
4. After this, save and deploy the changes to the org and deploy the parent component to the lightning page.
There will be no change in the input to select the value, but this is how we can do it programmatically by defining a custom event listener in the LWC component.

This way, we can handle a child-to-parent event in Salesforce lightning web components programmatically by using the addEventListner method.
Publish Subscriber model in Lightning Web Component
In Salesforce Lightning Web Components (LWC), the “Publish Subscriber” model is a design pattern where one component acts as a “publisher” to show an event, and other components can “subscribe” to that event to receive and react to the information, allowing for communication between components that aren’t necessarily directly related in the DOM hierarchy.
After the Salesforce Summer ’20 major release, the publisher model ‘pubsub’ was retired and replaced with the Lightning Message Service (LMS), which provides a standard way to implement the Publish-Subscribe Pattern for communication between components that do not have a direct relationship.
The Lightning Message Service is supported for LWC components, Aura Components, and Visualforce pages.
Implement the Publish-Subscribe Model in LWC for Event handling using Lightning Message Service
First, we need to create the Lightning message channel folder and an LMS file, and for that, navigate to the “force-app/main/default/messageChannels“. If the messageChannels folder is not there, you must create it.
1. Inside the messageChannels, create an XML file MyMessageChannel.messageChannel-meta.xml and enter the code below in that file.
?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata"
fqn="MyMessageChannel">
<isExposed>true</isExposed>
<lightningMessageFields>
<fieldName>message</fieldName>
</lightningMessageFields>
</LightningMessageChannel>2. After this, we will create a Listener Component to subscribe the event and handle the message. Now, for the logic, enter the code below in the Js file of the listener component.
import { LightningElement, wire } from 'lwc';
import { subscribe, unsubscribe, MessageContext } from 'lightning/messageService';
import SAMPLE_MESSAGE_CHANNEL from '@salesforce/messageChannel/MyMessageChannel__c';
export default class ListenerComponent extends LightningElement {
messageReceived;
subscription = null;
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscribeToMessageChannel();
}
subscribeToMessageChannel() {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
MY_MESSAGE_CHANNEL,
(message) => this.handleMessage(message)
);
}
}
handleMessage(message) {
this.messageReceived = message.message;
}
disconnectedCallback() {
unsubscribe(this.subscription);
this.subscription = null;
}
}2. Enter the code below in the Listener Component’s HTML file to display the publisher component’s message.
<template>
<lightning-card title="Listener Component">
<p class="slds-m-around_medium">Message: {messageReceived}</p>
</lightning-card>
</template>3. To publish the event, we will create a Publisher component to dispatch an event to send a message to other components, and for that logic, enter the code below in the Js file of the publisher component.
import { LightningElement, track, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import MY_MESSAGE_CHANNEL from '@salesforce/messageChannel/MyMessageChannel__c';
export default class PublisherComponent extends LightningElement {
@track messageToSend;
@wire(MessageContext)
messageContext;
handleInputChange(event) {
this.messageToSend = event.target.value;
}
sendMessage() {
const message = {
message: this.messageToSend
};
publish(this.messageContext, MY_MESSAGE_CHANNEL, message);
}
}4. Enter the code below in the HTML file of the publisher component that will take the text input and send a message with a button click.
<template>
<lightning-card title="Publisher Component">
<lightning-input label="Enter Message" onchange={handleInputChange}></lightning-input>
<lightning-button label="Send Message" onclick={sendMessage} class="slds-m-top_medium"></lightning-button>
</lightning-card>
</template>5. Enter the code below in the publisher and listner components to expose them for the lightning pages by using the code below in the LightningComponentBundle.
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>6. Deploy both the components on the Lightning page, then enter the text message in the input field of the publisher component, and as we click the send button, the exact text will appear in the listener component.

This way, we can handle the events between the Lightning web components that do not have a direct relationship using the Lightning message service.
Conclusion
In this Salesforce tutorial, we have learned about event handling in Salesforce Lightning web components for parent-to-child and child-to-parent relationships using public methods and public properties. We also used eventListner method to create a custom event call.
After that, we also discussed the Publish-Subscribe model that enables loosely coupled components to communicate without a direct hierarchical relationship, but as of now, we don’t use “publisher-subscriber,” and it is replaced by the Lightning Message Service (LMS) that handles events for objects with no direct relationship.
You may also like to read:
- Call Apex Methods From LWC in Salesforce
- Create and Deploy LWC Component in Salesforce
- Add Custom Validation in Salesforce Lightning Web Components
- Scheduler Apex in Salesforce With Examples
I am Bijay Kumar, the founder of SalesforceFAQs.com. Having over 10 years of experience working in salesforce technologies for clients across the world (Canada, Australia, United States, United Kingdom, New Zealand, etc.). I am a certified salesforce administrator and expert with experience in developing salesforce applications and projects. My goal is to make it easy for people to learn and use salesforce technologies by providing simple and easy-to-understand solutions. Check out the complete profile on About us.