How to work with Lightning Message Service in Salesforce?

on

|

views

and

comments

In Winter 20 Salesforce Introduce the new feature Lightning Message Service & it is generally available in Summer 20. LMS allows you to communicate between AURA, LWC & VF Page including the Utility Items as well. LMS allows publishing the event across the lightning environment that can be handled by either AURA, LWC and VF pages. This sounds like an Application Event in Aura Component however this is limited to Aura Components only.

  1. LMS is the first Salesforce technology which enables VF pages to communicate with Lightning Components anywhere in lightning pages including utility 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.

  1. In LWC we can access Lightning Message Channel with the scoped module @salesforce/messageChannel
  2. In Visualforce, we can use global variable $MessageChannel
  3. In Aura, use lightning:messageChannel in your component

How to Create a Lightning Message Channel

We can create LMS using VSCode.

To Create LMS you need to create a folder under force-app/main/default folder and the Folder name will be “messageChannels“.

After you have created the folder then we need to create a file and the structure of the file will be MyMessageChannel.messageChannel-meta.xml. Where “MyMessageChannel” is the name of the LMS and you can name it as per your requirement. Once you have created the file, we need to put some XML code which looks like below

<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>SampleMessageChannel</masterLabel>
    <isExposed>true</isExposed>
    <description>This is a sample Lightning Message Channel.</description>
    <lightningMessageFields>
        <fieldName>recordId</fieldName>
        <description>This is the record Id that changed</description>
    </lightningMessageFields>
    <lightningMessageFields>
        <fieldName>message</fieldName>
        <description>This is sample message</description>
    </lightningMessageFields>
    <lightningMessageFields>
        <fieldName>source</fieldName>
        <description>This is the source message</description>
    </lightningMessageFields>
    <lightningMessageFields>
        <fieldName>recordData</fieldName>
        <description>The current data representing the record that changed</description>
    </lightningMessageFields>
</LightningMessageChannel>

Where lightningMessageFields tag is used to create the fields/parameters that we need to send via event/lms. We can create many fields we wan.

Now, Add the entry for Lightning Message in Package.xml

<types>
		<members>*</members>
		<name>LightningMessageChannel</name>
	</types>

Now. Let’s create Lightning Component & Lightning Web Component along with the VF page to publish and subscribe the LMS.

Create VF Page and use below code.

To subscribe, publish or unsubscribe the LMS using VF we use sforce.one API

<apex:page lightningStylesheets="true">

    <apex:includeScript value="/sforce/one/49.0/api.js"></apex:includeScript>
    <apex:includeScript value="/soap/ajax/49.0/connection.js"></apex:includeScript>
    <apex:includeScript value="/soap/ajax/49.0/apex.js"></apex:includeScript>

    <apex:slds />
    <div>
        <p>Subscribe to SampleMessageChannel</p>
        <button onclick="subscribe_Message_Channel()">Subscribe</button>
        <div id="subscMessage" style="color:red"></div>
        <p>Unsubscribe from SampleMessageChannel</p>
        <button onclick="unsubscribe_Message_Channel()">Unsubscribe</button>
        <div id="unsubscMessage" style="color:red"></div>
        <p>Publish a message from VF</p>
        <button onclick="publishMC()">Publish</button>
        <br/>
        <br/>
        <p>Received message:</p>
        <textarea id="MCMessageTextArea" rows="10" style="disabled:true;resize:none;width:100%;" />
    </div>
    <script>

        // Load the MessageChannel token in a variable
        var SAMPLEMC = "{!$MessageChannel.SampleMessageChannel__c}";
        var subscriptionToMC;

        function onMCPublished(message) {
            var textArea = document.querySelector("#MCMessageTextArea");
            textArea.innerHTML = message ? JSON.stringify(message, null, '\t') : 'no message payload';
        }

        function subscribe_Message_Channel() {
            if (!subscriptionToMC) {
                subscriptionToMC = sforce.one.subscribe(SAMPLEMC, onMCPublished);
                var divAr = document.querySelector("#subscMessage");
                divAr.innerHTML = 'Message Channel Subscribed! ';
                var divAr = document.querySelector("#unsubscMessage");
                divAr.innerHTML = '';

            }
        }

        function unsubscribe_Message_Channel() {
            if (subscriptionToMC) {
                sforce.one.unsubscribe(subscriptionToMC);
                subscriptionToMC = null;
                var divAr = document.querySelector("#unsubscMessage");
                divAr.innerHTML = 'Message Channel UnSubscribed! ';
                var divAr = document.querySelector("#subscMessage");
                divAr.innerHTML = '';
            }
        }

        function publishMC() {
            const payload = {
                recordId: "003HSGHHJDHJHE637",
                recordData: { value: "Amit Singh" },
                channel: 'SFDCPanther',
                source: 'VF'
            }
            sforce.one.publish(SAMPLEMC, payload);
        }

    </script>
</apex:page>

<apex:page lightningStylesheets="true">
<apex:includeScript value="/sforce/one/49.0/api.js"></apex:includeScript>
<apex:includeScript value="/soap/ajax/49.0/connection.js"></apex:includeScript>
<apex:includeScript value="/soap/ajax/49.0/apex.js"></apex:includeScript>
<apex:slds />
<div>
<p>Subscribe to SampleMessageChannel</p>
<button onclick="subscribe_Message_Channel()">Subscribe</button>
<div id="subscMessage" style="color:red"></div>
<p>Unsubscribe from SampleMessageChannel</p>
<button onclick="unsubscribe_Message_Channel()">Unsubscribe</button>
<div id="unsubscMessage" style="color:red"></div>
<p>Publish a message from VF</p>
<button onclick="publishMC()">Publish</button>
<br/>
<br/>
<p>Received message:</p>
<textarea id="MCMessageTextArea" rows="10" style="disabled:true;resize:none;width:100%;" />
</div>
<script>
// Load the MessageChannel token in a variable
var SAMPLEMC = "{!$MessageChannel.SampleMessageChannel__c}";
var subscriptionToMC;
function onMCPublished(message) {
var textArea = document.querySelector("#MCMessageTextArea");
textArea.innerHTML = message ? JSON.stringify(message, null, '\t') : 'no message payload';
}
function subscribe_Message_Channel() {
if (!subscriptionToMC) {
subscriptionToMC = sforce.one.subscribe(SAMPLEMC, onMCPublished);
var divAr = document.querySelector("#subscMessage");
divAr.innerHTML = 'Message Channel Subscribed! ';
var divAr = document.querySelector("#unsubscMessage");
divAr.innerHTML = '';
}
}
function unsubscribe_Message_Channel() {
if (subscriptionToMC) {
sforce.one.unsubscribe(subscriptionToMC);
subscriptionToMC = null;
var divAr = document.querySelector("#unsubscMessage");
divAr.innerHTML = 'Message Channel UnSubscribed! ';
var divAr = document.querySelector("#subscMessage");
divAr.innerHTML = '';
}
}
function publishMC() {
const payload = {
recordId: "003HSGHHJDHJHE637",
recordData: { value: "Amit Singh" },
channel: 'SFDCPanther',
source: 'VF'
}
sforce.one.publish(SAMPLEMC, payload);
}
</script>
</apex:page>
view raw LMSDemo.html hosted with ❤ by GitHub
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>SampleMessageChannel</masterLabel>
<isExposed>true</isExposed>
<description>This is a sample Lightning Message Channel.</description>
<lightningMessageFields>
<fieldName>recordId</fieldName>
<description>This is the record Id that changed</description>
</lightningMessageFields>
<lightningMessageFields>
<fieldName>message</fieldName>
<description>This is sample message</description>
</lightningMessageFields>
<lightningMessageFields>
<fieldName>source</fieldName>
<description>This is the source message</description>
</lightningMessageFields>
<lightningMessageFields>
<fieldName>recordData</fieldName>
<description>The current data representing the record that changed</description>
</lightningMessageFields>
</LightningMessageChannel>

Create LWC

Subscriber Component

To use LMS in LWC first step is that we need to import the methods from the lightning/MessageChannel library and import the Message channel

import {
  subscribe,
  unsubscribe,
  APPLICATION_SCOPE,
  MessageContext
} from "lightning/messageService";

import SAMPLEMC from "@salesforce/messageChannel/SampleMessageChannel__c";

Where SampleMessageChannel is the name of the Message Channel

<!-- subscribeComponent.html -->
<template>
<lightning-card title="Subscriber Component" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<p>MessageChannel: SampleMessageChannel</p>
<br />
<lightning-button
label="Subscribe"
variant="brand"
disabled={isDisabled}
onclick={subscribeMC}
>
</lightning-button>
&nbsp; &nbsp;
<lightning-button
label="Unsubscribe"
variant="destructive"
disabled={isDisabledUnsb}
onclick={unsubscribeMC}
>
</lightning-button>
<br />
<p>Received message:</p>
<textarea
id="receivedMessageTextArea"
style="width: 435px;height: 200px;"
class="textareaReceivedMessage"
rows="7"
disabled
>
{receivedMessage}</textarea
>
</div>
</lightning-card>
</template>
// subscribeComponent.js
import { LightningElement, wire } from "lwc";
import {
subscribe,
unsubscribe,
APPLICATION_SCOPE,
MessageContext
} from "lightning/messageService";
import SAMPLEMC from "@salesforce/messageChannel/SampleMessageChannel__c";
export default class SubscribeComponent extends LightningElement {
@wire(MessageContext)
messageContext;
subscription = null;
receivedMessage;
isDisabled = false;
isDisabledUnsb = true;
subscribeMC() {
this.isDisabled = true;
this.isDisabledUnsb = false;
if (this.subscription) {
return;
}
this.subscription = subscribe(
this.messageContext,
SAMPLEMC,
message => {
this.handleMessage(message);
},
{ scope: APPLICATION_SCOPE }
);
}
unsubscribeMC() {
unsubscribe(this.subscription);
this.subscription = null;
this.isDisabled = false;
this.isDisabledUnsb = true;
}
handleMessage(message) {
this.receivedMessage = message
? JSON.stringify(message, null, "\t")
: "no message payload";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>48.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>

Publisher Components

The first step is that we need to import the methods from the lightning/MessageChannel library and import the Message channel

<!-- publisherComponent.html -->
<template>
<lightning-card title="Publisher Component" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<p>MessageChannel: SampleMessageChannel</p>
<br>
<lightning-button label="Publish" variant="brand" onclick={handleClick}></lightning-button>
</div>
</lightning-card>
</template>
// publisherComponent.js
import { LightningElement, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import SAMPLEMC from '@salesforce/messageChannel/SampleMessageChannel__c';
export default class PublisherComponent extends LightningElement {
@wire(MessageContext)
messageContext;
handleClick() {
const message = {
recordId: '001xx000003NGSFAA4',
message : "This is simple message from LWC",
source: "LWC",
recordData: {accountName: 'Burlington Textiles Corp of America'}
};
publish(this.messageContext, SAMPLEMC, message);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>48.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>

Create Aura Components

Publisher Component

<!-- publisherComponent.cmp -->
<aura:component
implements="flexipage:availableForAllPageTypes, flexipage:availableForRecordHome"
>
<lightning:card
iconName="custom:custom14"
title="Aura Publisher Component"
footer="Aura Publisher Component"
>
<p class="slds-p-horizontal_small">
<lightning:button
label="Send Payload"
variant="brand"
onclick="{! c.handleClick }"
/>
<lightning:messageChannel
type="SampleMessageChannel__c"
aura:id="sampleMessageChannel"
/>
</p>
</lightning:card>
</aura:component>
// publisherController.js
({
handleClick: function(component, event, helper) {
var payload = {
recordId: "001HSGKDHJ6834BHS",
recordData: {
accountName: "Amit Singh"
},
source: "Aura Component",
channel: "SFDCPanther"
};
component.find("sampleMessageChannel").publish(payload);
}
});

Subscribe Component

<!-- mySubscriberComponent.cmp -->
<aura:component
implements="flexipage:availableForAllPageTypes, flexipage:availableForRecordHome"
>
<aura:attribute name="recordValue" type="String" />
<lightning:messageChannel
type="SampleMessageChannel__c"
onMessage="{!c.handleMessage}"
scope="APPLICATION"
/>
<lightning:card title="Aura Subscriber Component" iconName="custom:custom14">
<p class="slds-p-horizontal_small">
Message from Publisher Component: <br />
<textarea
id="receivedMessageTextArea"
class="textareaReceivedMessage"
rows="7"
style="width: 435px;height: 200px;"
disabled="true"
>
{!v.recordValue}
</textarea>
</p>
</lightning:card>
</aura:component>
({
handleMessage: function(cmp, event, helper) {
// Read the message argument to get the values in the message payload
if (event != null && event.getParams() != null) {
let params = event.getParams();
cmp.set("v.recordValue", JSON.stringify(params, null, "\t"));
}
}
});

Now, we are done with the development. Time to test it. Refer video.

To Learn about lightning web component get the my Udemy course from here.

https://www.udemy.com/course/salesforce-lightning-web-component/

Resource:-

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

https://amitsalesforce.blogspot.com/2019/10/lightning-message-service-lms.html

Happy Learning 🙂 #KeepLearning #KeepSharing

Amit Singh
Amit Singhhttps://www.pantherschools.com/
Amit Singh aka @sfdcpanther/pantherschools, a Salesforce Technical Architect, Consultant with over 8+ years of experience in Salesforce technology. 21x Certified. Blogger, Speaker, and Instructor. DevSecOps Champion
Share this

Leave a review

Excellent

SUBSCRIBE-US

Book a 1:1 Call

Must-read

How to Utilize Salesforce CLI sf (v2)

The Salesforce CLI is not just a tool; it’s the cornerstone of development on the Salesforce Platform. It’s your go-to for building, testing, deploying, and more. As one of the most important development tools in our ecosystem

Save the day of a Developer with Apex Log Analyzer

Table of Contents What is Apex Log Analyzer? Apex Log Analyzer, a tool designed with Salesforce developers in mind, is here to simplify and accelerate your...

Salesforce PodCast

Introduction Hey Everyone, Welcome to my podcast, the first-ever podcast in India for Salesforce professionals. Achievement We are happy to announce that we have been selected as Top...

Recent articles

More like this

3 COMMENTS

  1. Good example. I’m newby, and the only thing I can’t figure out, is how to invoke a function in subscriber component after Publish complete.
    Is there any callbacks or something?

LEAVE A REPLY

Please enter your comment!
Please enter your name here