In Winter 20 Salesforce Introduce the new feature Lightning Message Service 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.
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.
Let see how we can implements this
MyMessageChannel.messageChannel-meta.xml
And Package.xml should be like below
package.xml
LMSVisualforcePage.page
lMCWebComponentDemo.html
Reference:
Some other related post:
Thanks
Amit Chaudhary
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
When to use Lightning Message Service.
In Lightning Experience, if we want a Visualforce page 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. I hope you have VsCode installed in your machine if not please check this post. 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>
<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
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>
Right click on LightningMessageChannel file and Deploy in Org.<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>LightningMessageChannel</name>
</types>
<version>47.0</version>
</Package>
Create 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>
<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
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);
}
}
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);
}
}
- First, we have to ensure that we import both the methods to interact with LMS import { publish,subscribe,unsubscribe,createMessageContext,releaseMessageContext } from 'lightning/messageService';
import SAMPLEMC from "@salesforce/messageChannel/MyMessageChannel__c";
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>
<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>
Reference:
- https://releasenotes.docs.salesforce.com/en-us/winter20/release-notes/rn_lc_message_channel.htm
- https://developer.salesforce.com/blogs/2019/10/lightning-message-service-developer-preview.html
- https://developer.salesforce.com/docs/component-library/bundle/lightning-message-service/documentation
Some other related post:
- Event Communication in Lightning Web Components
- Event Communication in Lightning Components
- Setup VsCode for Salesforce
- Lightning We Components
Thanks
Amit Chaudhary