Send data using Lightning Message Service in LWC
Earlier when we had to send data from one component to another component that is not within the hierarchy then we were relying upon PubSub.
It's a library that Salesforce provided that's dependent on Publish and Subscribe model.
But that approach is a bit roundabout and tedious for developers to use.
So Salesforce came up with Lightning Message Service which is used to send data from one LWC Component to another LWC Component. Also, it's used for communication between LWC, Aura, and Visualforce pages too.
Let's look at how to send data using Lightning Message Service in LWC.
The first thing that we need to create is a Message Channel. We cannot create a Message Channel (via an XML file) from the Salesforce Developer Org or Sandbox. We need to create it from VS Code and push it to the respective org.
Here is the XML file used to create a MessageChannel.
<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel>
<masterLabel>AccountData</masterLabel>
<isExposed>true</isExposed>
<description
>This is a channel which is used by LWC component to send data</description>
<!-- Am creating two fields that will be eventually
used to send data -->
<lightningMessageFields>
<description>This is the Id of the record</description>
<fieldName>recordId</fieldName>
</lightningMessageFields>
<lightningMessageFields>
<description>This is the of the record</description>
<fieldName>name</fieldName>
</lightningMessageFields>
</LightningMessageChannel>
Create an XML file with the extension .messageChannel-meta.xml
This is the template file that transmits the data on click of the button.
<template>
<lightning-button label="send data" onclick={handleClick}></lightning-button>
</template>
This is the JavaScript file of the Web Lightning Web Component.
import { LightningElement, wire } from "lwc";
//1. Importing the named imports
//[library to publish data and the message channel]
import { publish, MessageContext } from "lightning/messageService";
import ACCOUNT_CHANNEL from "@salesforce/messageChannel/AccountDataMessageChannel__c";
export default class PublisherComponent extends LightningElement {
//2. Wiring the MessageContext to a property
@wire(MessageContext)
messageContext;
//3. Handling the user input.
//which in our case is going to be a button click
handleClick() {
const messaage = {
recordId: "001xx000003NGSFAA4",
name: "Burlington Textiles of America"
};
//4. Publishing the message
publish(this.messageContext, ACCOUNT_CHANNEL, messaage);
}
}
This is a template that is going to receive the data that the other component publishes using the Message Channel.
We will only be receiving the data when we subscribe.
<template>
<lightning-button
label="subscribe"
onclick={handleSubscribe}
></lightning-button>
<lightning-button
label="unsubscribe"
onclick={handleUnsubscribe}
></lightning-button>
<lightning-button label="clear" onclick={handleClear}></lightning-button>
{receivedMessage}
</template>
This is the JavaScript controller of the Web Component that subscribes to the Message Channel (on click of the button on the template file).
import { LightningElement, wire } from "lwc";
//1. Import all the named imports
import {
subscribe,
unsubscribe,
MessageContext
} from "lightning/messageService";
import ACCOUNT_CHANNEL from "@salesforce/messageChannel/AccountDataMessageChannel__c";
export default class SubscriberComponent extends LightningElement {
//2. Wiring MessageContext to a property
@wire(MessageContext)
messageContext;
receivedMessage;
subscription = null;
//3. Handling the user input
handleSubscribe() {
console.log("in handle subscribe");
if (this.subscription) {
return;
}
//4. Subscribing to the message channel
this.subscription = subscribe(
this.messageContext,
ACCOUNT_CHANNEL,
(message) => {
this.handleMessage(message);
}
);
}
handleMessage(message) {
this.receivedMessage = message
? JSON.stringify(message, null, "\t")
: "no message";
}
handleUnsubscribe() {
console.log("in handle unsubscribe");
unsubscribe(this.subscription);
this.subscription = null;
}
handleClear() {
this.receivedMessage = null;
}
}
Hope this is helpful!