Lightning Web Components (LWC) is a modern and lightweight framework by Salesforce for building web components on the Lightning Platform. One of the key aspects of building efficient and modular applications in LWC is effective communication between components. In this blog post, we’ll explore various techniques for event handling in LWC to facilitate communication between components.
When Components Start Talking: Understanding Events in LWC
Let’s kick things off by understanding the basics of events in LWC.
Events in LWC are a way through which one component can communicate with another within the same DOM tree. Through events, components share information and engage in action resulting in more dynamic and responsive applications.
The Emissaries: Different types of Events
There are two types of events in LWC:
- Component Events – These types of events are used for communication between components that have a parent-child relationship. The event bubbles up from the child to the parent, with the latter having the opportunity to handle it.
- Application Events – These events involve communication between any two components in the DOM tree, even if they do not have a parent-child relationship.
A Relay Race: Propagation of Events
Understanding how events are propagated in LWC is critical to mastering event handling in component communications.
Stage 1: The Bubbling Phase
Bubbling is similar to rising bubbles in a water vessel. When an event occurs, it starts propagating upwards in the DOM tree, from child nodes to parent nodes.
Stage 2: The Capturing Phase
Unlike the bubbling phase, the capturing phase is a descent from the modern parent to the deepest child. In LWC, it doesn’t play as significant a role as the bubbling phase, but it’s key in understanding the whole cycle.
Stage 3: The Target Phase?
Onto the last stage, where the actual event occurred. From here, both the bubbling and capturing phases emerge, making it the crossroads of event propagation.
Making it Official: Declaring Events
To use events in LWC, we need to declare them first. The declaration involves creating a custom event and passing any information that needs to be communicated in the detail property.
You can do this like this:
const event = new CustomEvent('eventname', {detail: yourData});
Naming Conventions
While naming events, follow kebab-case (a case where words are demarcated by hyphens). Also, ensure that the event name corresponds to the data it carries or the action it invokes.
The Dispatch: Firing Events
After creating our event, we can dispatch it using the dispatchEvent() method.
Here’s how you do it:
this.dispatchEvent(event);
Communicating the Event: Parent-Child Component Interaction
In LWC, a custom event created in a child component can be listened to and handled in a parent component. The event bubbles up from the child component to any ancestor components until it is handled.
Inside the Event: Event Payload
Any data that is transferred from the source component to other components through an event is called event payload. It’s placed in the detail property of the event.
For a component event, the component originating the event can pass data to any listening parent components.
The Listener: Handling Events
Components can ‘listen’ for events by specifying the event name in a template. Once the event is detected, an event handler function is run.
You can define the event handler like this:
<template> <c-child oncustomevent={handleCustomEvent}></c-child> </template>
A Dialogue: Two-way Communication
In some situations, you might need a two-way communication between child and parent. For example, a parent component wants to fetch some data from a child component. This can be achieved through public properties and methods.
1. Parent-to-Child Communication (Using Props):
In LWC, parent-to-child communication is straightforward using properties (props). Properties allow you to pass data from a parent component to a child component. Here’s a basic example:
Parent Component:
<!-- parentComponent.html --> <template> <c-child-component message={parentMessage}></c-child-component> </template>
// parentComponent.js import { LightningElement } from 'lwc'; export default class ParentComponent extends LightningElement { parentMessage = 'Hello from parent!'; }
Child Component:
<!-- childComponent.html --> <template> <p>{message}</p> </template>
// childComponent.js import { LightningElement, api } from 'lwc'; export default class ChildComponent extends LightningElement { @api message; }
2. Child-to-Parent Communication (Using Custom Events):
Child-to-parent communication is achieved through custom events. A child component can emit a custom event that the parent component listens for. Here’s a simple example:
Child Component:
<!-- childComponent.html --> <template> <button onclick={notifyParent}>Notify Parent</button> </template>
// childComponent.js import { LightningElement } from 'lwc'; export default class ChildComponent extends LightningElement { notifyParent() { const customEvent = new CustomEvent('notify', { detail: 'Message from child' }); this.dispatchEvent(customEvent); } }
Parent Component:
<!-- parentComponent.html --> <template> <c-child-component onnotify={handleNotify}></c-child-component> </template>
// parentComponent.js import { LightningElement } from 'lwc'; export default class ParentComponent extends LightningElement { handleNotify(event) { const messageFromChild = event.detail; // Handle the message from the child component } }
3. Sibling Communication (Using a Shared JavaScript File):
When two sibling components need to share data, a shared JavaScript file can be used. This file contains functions or variables that both components can import and use. Here’s a basic example:
Shared JavaScript File:
// sharedData.js let sharedValue; export function setSharedValue(value) { sharedValue = value; } export function getSharedValue() { return sharedValue; }
Sibling Components:
// sibling1.js import { LightningElement } from 'lwc'; import { setSharedValue } from 'c/sharedData'; export default class Sibling1 extends LightningElement { // Set the shared value setSharedValue('Hello from Sibling 1!'); }
// sibling2.js import { LightningElement } from 'lwc'; import { getSharedValue } from 'c/sharedData'; export default class Sibling2 extends LightningElement { // Get the shared value connectedCallback() { const sharedValue = getSharedValue(); // Use the shared value } }
Conclusion:
Effective communication between components is crucial for building modular and scalable applications in LWC. Whether it’s passing data from a parent to a child, emitting custom events, or sharing data between siblings, LWC provides various tools for seamless event handling. Choose the method that best fits your use case, keeping in mind the relationships between your components and the nature of the data being communicated.
Good this one it’s very helpful to me
Thank You!