In Winter 20 Salesforce Introduce the new feature Lightning Message Service (LMS) and it is generally available in Summer 20. Lightning Message Service (LMS) allow you to communicate between Visualforce and Lightning Components (Aura and LWC both) on any Lightning page. LMS API allow you to publish message throughout the lightning experience and subscribe the same message anywhere with in lightning page.
It is similar to Aura Application Events to communication happens between components. We’ll also see a demonstration of how scoped messaging works to make subscribers automatically activate and deactivate when certain parts of the UI are active.
What is Lightning Message Service?
Lightning message service, a cross DOM client side messaging feature that, was just made generally available in Summer 20. Lightning Message Service is based on a new metadata type Lightning Message Channels. We need to use Lightning Message Channel to access the Lightning Message Service API.
- In LWC we can access Lightning Message Channel with the scoped module
@salesforce/messageChannel
. - In Visualforce, we can use global variable
$MessageChannel
. - In Aura, use
lightning:messageChannel
in your component
Principle of Message Service
- Client-side event bus between DOM branches
- LWC, Aura and Visualforce as Equals citizens
- Don’t Be Surprising ( Scope)
When to use Lightning Message Service.
In Lightning Experience, if we want a Visualforce page or Aura to communicate with a Lightning web component then we have to implement a custom publish-subscribe solution because this is currently not possible with LWC Event. Now, we can use the Lightning Message Service API to handle this communication.
Let see how we can implements this
Create Lightning Message Channel
Currently we can create Lightning Message channel with Metadata API. You can create the same with the help of VsCode. You need to create one DX project then you need to place your message channel definition with the suffix .messageChannel-meta.xml
in the force-app/main/default/messageChannels directory. like below folder structure.
MyMessageChannel.messageChannel-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>MyMessageChannel</masterLabel>
<isExposed>true</isExposed>
<description>This Lightning Message Channel sends information from VF to LWC</description>
<lightningMessageFields>
<fieldName>messageToSend</fieldName>
<description>message To Send</description>
</lightningMessageFields>
<lightningMessageFields>
<fieldName>sourceSystem</fieldName>
<description>My source?</description>
</lightningMessageFields>
</LightningMessageChannel>
And Package.xml should be like below. then Right click on LightningMessageChannel file and Deploy in Org
package.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>LightningMessageChannel</name>
</types>
<version>47.0</version>
</Package>
Ok now our Lightning Message Channel is ready. Let see how we can use the same.
Create Visualforce page and LWC
Let see how to use LMS with Visualforce page and LWC.
1) LMS with Visualforce page
Salesforce introduced new sforce.one APIs — publish, subscribe, and unsubscribe — in Visualforce to interact with LMS (only available in Lightning).
LMSVisualforcePage.page
<apex:page>
<div>
<p>Enter Your Message Here:</p>
<input type="text" id="theMessage" />
<button onclick="publishMC()"> Publish Msg</button>
<br/><br/>
<button onclick="subscribeMC()">Subscribe</button>
<button onclick="unsubscribeMC()">Unsubscribe</button>
<br/>
<br/>
<p>Received message:</p>
<label id="MCMessageText"/>
</div>
<script>
// Load the MessageChannel token in a variable
var SAMPLEMC = "{!$MessageChannel.MyMessageChannel__c}";
var subscriptionToMC;
function publishMC() {
const message = {
messageToSend: document.getElementById('theMessage').value,
sourceSystem: "From VisualForce Page"
};
sforce.one.publish(SAMPLEMC, message);
}
// Display message in the textarea field
function displayMessage(message) {
var textLabel = document.querySelector("#MCMessageText");
textLabel.innerHTML = message ? JSON.stringify(message, null, '\t') : 'no message payload';
}
function subscribeMC() {
if (!subscriptionToMC) {
subscriptionToMC = sforce.one.subscribe(SAMPLEMC, displayMessage);
}
}
function unsubscribeMC() {
if (subscriptionToMC) {
sforce.one.unsubscribe(subscriptionToMC);
subscriptionToMC = null;
}
}
</script>
</apex:page>
- “
subscribeMC
” method is used to subscribe the Message Channel with “sforce.one.subscribe(SAMPLEMC, displayMessage);"
- “
unsubscribeMC
” method to unsubscribe the Message Channel with “sforce.one.unsubscribe(subscriptionToMC);
“ - “
publishMC
” to publish the message withe the help of “sforce.one.publish(SAMPLEMC, message);"
2) LMS with Lightning Web Components
- First, we have to ensure that we import both the methods to interact with LMS like below code.
import { publish,subscribe,unsubscribe,createMessageContext,releaseMessageContext } from 'lightning/messageService';
import SAMPLEMC from "@salesforce/messageChannel/MyMessageChannel__c";
Let see the sample code.
lMCWebComponentDemo.html
<template>
<lightning-card title="LMC Web Component" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<p>MessageChannel: MyMessageChannel__c</p>
<br>
</div>
<!-- Default/basic -->
<div class="slds-p-around_medium lgc-bg">
<lightning-input type="text" label="Enter some text" value={myMessage} onchange={handleChange}></lightning-input>
<lightning-button label="Publish" onclick={publishMC}></lightning-button>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-button label="Subscribe" onclick={subscribeMC}></lightning-button>
<lightning-button label="Unsubscribe" onclick={unsubscribeMC}></lightning-button>
<p>Latest Message Received</p>
<lightning-formatted-text value={receivedMessage}></lightning-formatted-text>
</div>
</lightning-card>
</template>
lMCWebComponentDemo.js
import { LightningElement,track } from 'lwc';
import { publish,subscribe,unsubscribe,createMessageContext,releaseMessageContext } from 'lightning/messageService';
import SAMPLEMC from "@salesforce/messageChannel/MyMessageChannel__c";
export default class LMCWebComponentDemo extends LightningElement {
@track receivedMessage = '';
@track myMessage = '';
subscription = null;
context = createMessageContext();
constructor() {
super();
}
handleChange(event) {
this.myMessage = event.target.value;
}
publishMC() {
const message = {
messageToSend: this.myMessage,
sourceSystem: "From LWC"
};
publish(this.context, SAMPLEMC, message);
}
subscribeMC() {
if (this.subscription) {
return;
}
this.subscription = subscribe(this.context, SAMPLEMC, (message) => {
this.displayMessage(message);
});
}
unsubscribeMC() {
unsubscribe(this.subscription);
this.subscription = null;
}
displayMessage(message) {
this.receivedMessage = message ? JSON.stringify(message, null, '\t') : 'no message payload';
}
disconnectedCallback() {
releaseMessageContext(this.context);
}
}
Lightning Message Service Demo
Summary
Use Lightning message service to communicate across the DOM within a Lightning page. Communicate between Visualforce pages embedded in the same Lightning page, Aura components, and Lightning web components, including components in a utility bar and pop-out utilities. Source: Communicate Across the DOM with Lightning Message Service.
This blog post on Lightning Message Service (LMS) was incredibly insightful! I appreciate the clear explanations and practical examples you provided for using MessageChannel. It has definitely deepened my understanding of cross-component communication in Lightning. Looking forward to more posts like this!