Lightning Message Service – LMS
LMS is a front-end/client side service that allows a quick channel to publish and subscribe to messages between all components on the page.
Finally we have an official Salesforce technology designed to enable communication between Visualforce and Lightning Components anywhere on a Lightning Page.
So, if you looked for a way to communicate between All interactions on the same Lightning Experience application instance — i.e. same browser tab. – look no further.
Instead of implementing a custom pub/sub framework, simpler and better off using the Standard Lightning Message Channel.
Lets get started…
Deploy your messageChannels
LMS channels are part of our org metadata so we will need to deploy the channel in order to get started.
- Create a Metadata Folder in your project named
messageChannels
- Create XML file inside this folder as
SampleMessageChannel.messageChannel-meta.xml
- Copy paste the following template
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata"> <masterLabel>SampleMessageChannel</masterLabel> <isExposed>true</isExposed> <description>This is a sample Lightning Message Channel.</description> <!-- FIELDS --> <lightningMessageFields> <description>This is the record Id that changed</description> <fieldName>recordId</fieldName> </lightningMessageFields> </LightningMessageChannel>
This example shows how to add a recordId
as lightningMessageFields
which will be part of the message payload.
Import the Message Channel to LWC
// imports { functions, context, scope } import { ..., ..., ... } from 'lightning/messageService'; import SAMPLEMC from '@salesforce/...';
Lightning Web Components
Publish : Fire the Event
// myPublisherComponent.js import { LightningElement, wire } from 'lwc'; import { MessageContext, releaseMessageContext, publish } from 'lightning/messageService'; import SAMPLEMC from "@salesforce/messageChannel/SampleMessageChannel__c"; export default class MyPublisherComponent extends LightningElement { // wired message context @wire(MessageContext) context; publishMC() { const message = { recordId: "some string" }; publish(this.context, SAMPLEMC, message); } disconnectedCallback() { releaseMessageContext(this.context); } }
Subscribe : Listen to the Event Message
// mySubscriberComponent.js import { LightningElement, track, wire } from 'lwc'; import { subscribe, APPLICATION_SCOPE, MessageContext , unsubscribe, releaseMessageContext } from 'lightning/messageService'; import SAMPLEMC from "@salesforce/messageChannel/SampleMessageChannel__c"; export default class MySubscriberComponent extends LightningElement { subscription = null; @wire(MessageContext) messageContext; @track receivedMessage = ''; subscribeMC() { if (this.subscription) { return; } this.subscription = subscribe(this.messageContext, SAMPLEMC, (message) => { this.handleMessage(message); }, { scope: APPLICATION_SCOPE }); } unsubscribeMC() { unsubscribe(this.subscription); this.subscription = null; } handleMessage(message) { this.receivedMessage = message ? JSON.stringify(message, null, '\t') : 'no message payload'; } disconnectedCallback() { releaseMessageContext(this.messageContext); } }
Invoking subscribeMC
method will start listening to the channel.
If we wish to start listening to the message channel from the moment the component has loaded – we can use the lifecycle method connectedCallback
to invoke it.
Example :
connectedCallback() { this.subscribeMC(); }
Aura
- Use
lightning:messageChannel
Publish
<!-- myPublisherComponent.cmp --> <aura:component> <lightning:button onclick="{!c.publishMC}"> <lightning:messageChannel type="SampleMessageChannel__c" aura:id="sampleMessageChannel"/> </aura:component>
// myPublisherComponentController.js ({ publishMC: function(component, event, helper) { var message = { recordId: "some string", recordData: { value: "some value" } }; component.find("sampleMessageChannel").publish(message); } })
Subscribe
<!-- mySubscriberComponent.cmp --> <aura:component> <aura:attribute name="recordValue" type="String"/> <lightning:formattedText value="{!v.recordValue}" /> <lightning:messageChannel type="SampleMessageChannel__c" onMessage="{!c.handleMessage}"/> </aura:component>
// mySubscriberComponentController.js ({ handleMessage: function(component, message, helper) { // Read the message argument to get the values in the message payload if (message != null && message.getParam("recordData") != null) { component.set("v.recordValue", message.getParam("recordData").value); } } })
Visualforce
- Use global variable
$MessageChannel
Publish
<apex:page> ... <script> // Load the Message Channel token in a variable const SAMPLEMC = "{!$MessageChannel.SampleMessageChannel__c}"; // Publish function publishMC() { const message = { recordId: "some string", recordData: { value: "some value" } } sforce.one.publish(SAMPLEMC, message); } </script> ... </apex:page>
Subscribe
<apex:page> ... <script> // Load the Message Channel token in a variable const SAMPLEMC = "{!$MessageChannel.SampleMessageChannel__c}"; let subscription; function handleMessage(message) { const textArea = document.querySelector("#messageTextArea"); textArea.innerHTML = message ? JSON.stringify(message, null, '\t') : 'no message payload'; } function subscribeMC() { if (!subscription) { subscription = sforce.one.subscribe(SAMPLEMC, handleMessage); } } function unsubscribeMC() { if (subscription) { sforce.one.unsubscribe(subscription); subscription = null; } } </script> ... </apex:page>
Thats all you are ready to communicate 🙂
At this time, Message Service does not support :
- Salesforce mobile app
- Lightning Out
- Lightning Communities
Resources:
- Lightning Message Service
- Message Service
- Subscribe and Unsubscribe from a Message Channel (LWC)
- Lightning Message Service Limitations
- Learn MOAR: Sample Gallery Updates for Summer ’20