Lightning Message Service (LMS) – Future of Communication

Lightning Message Service (LMS) is the first Salesforce feature that enables the communication between Visualforce Page, Aura Component, and LWC (Lightning Web Component) anywhere on the Lightning Page. It provides a simple API to publish messages throughout Lightning Experience and subscribe to messages that originated from anywhere within Lightning Experience. The only requirement is that all interactions have to originate from the same Lightning Experience application instance i.e, the same Browser Tab.

Lightning Message Service is a standard publish-subscribe library in the UI, enabling components in any part of the DOM to communicate. This is so useful so let’s just get into the implementation.

Implementation

In this implementation, we will publish a message from Visualforce Page and subscribe it from Aura Component, Lightning Web Component, and Utility Bar.

Lightning Message Channel

Lightning Message Channel (LMS) is a new type of metadata. It is a new lightweight, packageable component that we can create in our org and at runtime. We can publish and subscribe messages on it.

As of now, we can not create it from Salesforce User Interface. Create a new folder inside force-app > main > default in your VS code with name messageChannels.

Create a new file under messageChannels folder with the name TextMessageChannel.messageChannel-meta.xml where TextMessageChannel is our message channel name and we can access it using TextMessageChannel__c. The only required field for the message channel is masterLabel. Optional Boolean isExposed is used to make our message channel is available for other components.

This is enough to create the Lightning Message Channel. We can also use lightningMessageFields to create fields for the message channel and send it to the payload. We don’t require it in our demonstration. We will send a plain JSON. You can check more about lightningMessageFields here.

TextMessageChannel.messageChannel-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>TextMessageChannel</masterLabel>
    <isExposed>true</isExposed>
    <description>This is Text Message Channel to send/receive Text Message.</description>
</LightningMessageChannel>

Lightning Message Service in Visualforce Page

Create a Visualforce Page PublishedVF. Add markup to create a Text box and Button. Once the button is clicked, get the message channel using {!$MessageChannel.TextMessageChannel__c}. Create a JSON variable objMessage and property publishedText which has the text entered in the Text box. Use sforce.one.publish(textMessageChannel, objMessage) method to publish message where textMessageChannel is the reference of message channel and objMessage is the payload. We can use sforce.one.subscribe() and sforce.one.unsubscribe() as well to subscribe and unsubscribe but we are using this page to publish messages only.

PublishedVF.page

<apex:page>
    <apex:slds />
    <script>
        // Method to publish the message to message Channel
        function publishMessage(){
            var textMessageChannel = "{!$MessageChannel.TextMessageChannel__c}";            
            const objMessage = {
                "publishedText" : document.querySelector("#idText").value
            }
            sforce.one.publish(textMessageChannel, objMessage);
        }
    </script>
    
    <div class="slds-form-element">
        <label class="slds-form-element__label" for="form-element-01">Enter Message to Publish:</label>
        <br/>
        <div class="slds-form-element__control">
            <input type="text" id="idText" placeholder="Placeholder Text" class="slds-input"/>
        </div>
    </div>
    <br/>
    <button class="slds-button slds-button_brand" type="button" onclick="publishMessage()">Publish Message</button>
</apex:page>

Lightning Message Service in Aura Component

Create an Aura Component SubscribeAura. Add the below line to subscribe to the message channel:

<lightning:messageChannel type="TextMessageChannel__c" onMessage="{!c.subscribeHandler}"/>

Action subscribeHandler will be called once the message is published by PublishedVF page. Add the markup to display the attribute value for the retrievedMessage which will be set in subscribeHandler method. Aura Component will listen to the messages until the component is destroyed from DOM. Add toggle input to add conditional logic to subscribe and unsubscribe.

SubscribeAura.cmp

<aura:component implements="flexipage:availableForAllPageTypes">
    <aura:attribute name="retrievedMessage" type="String"/>
    <aura:attribute name="isSubscribed" type="Boolean" default="false"/>
    <!-- Subscribing to Message Channel-->
    <lightning:messageChannel type="TextMessageChannel__c" onMessage="{!c.subscribeHandler}"/>
    <lightning:card title="Aura Component">
        <lightning:layout>
            <lightning:layoutItem size="9">
                <!-- To display the Received Message-->
                <div class="slds-m-top_x-medium slds-p-around_medium" style="height:150px">
                    <p style="font-size:20px;">Received Message: </p> 
                    <p style="color:green;display:inline;font-weight:bold;font-size:25px;">
                        {!v.retrievedMessage}
                    </p>
                </div>
            </lightning:layoutItem>
            <lightning:layoutItem size="3">
                <lightning:input type="toggle" name="inputSubscribe" checked="default" 
                onchange="{!c.toggleSubscribe}" messageToggleActive="Subscribed" messageToggleInactive="Unsubscribed"/>
            </lightning:layoutItem>
        </lightning:layout>
        
    </lightning:card>
</aura:component>

Add toggle logic in JS Controller to update isSubscribed attribute. Add subscribeHandler method as well and use isSubscribed attribute to get or ignore the new message. If isSubscribed is true, we will get the publishedText from the event param and set the retrievedMessage attribute. If isSubscribed is false, we will ignore the message. This is how we can add our own custom Unsubscribe logic. We don’t have to do it for Visualforce page and Lightning Component as both has unsubscribe method.

SubscribeAuraController.js

Note: If there are any ‘&amp;&amp;’ in the below code, replace it with ‘&&’.

({
    toggleSubscribe : function(component, event, helper) {
        component.set("v.isSubscribed", event.getSource().get("v.checked"));
    },
    
    subscribeHandler : function(component, event, helper) {
        if(component.get("v.isSubscribed")){
            // Use event object to get the parameters.
            if (event != null && event.getParam("publishedText") != null) {
                component.set("v.retrievedMessage", event.getParam("publishedText"));
            }
        }
    }
})

Lightning Message Service in Lighting Web Component

Create Lightning Web Component subscribeLwc and add a markup to display the retrievedMessage. Add toggle input to Subscribe and Unsubscribe from the message channel. Add onchange handler for the toggle input.

subscribeLwc.html

<template>
    <lightning-card title="Lightning Web Component">
        <lightning-layout>
            <lightning-layout-item size="9">
                <div class="slds-p-left_medium" style="height:150px">
                    <p class="slds-text-heading_small" style="font-size:20px;">Received Message: </p> 
                    <p style="color:green;display:inline;font-weight:bold;font-size:25px;">
                        <lightning-formatted-text value={receivedMessage}></lightning-formatted-text>
                    </p>
                </div>
            </lightning-layout-item>
            <lightning-layout-item size="3">
                <lightning-input type="toggle" name="inputSubscribe" onchange={toggleSubscribe}
                    message-toggle-active="Subscribed" message-toggle-inactive="Unsubscribed">                       
                </lightning-input>
            </lightning-layout-item>
        </lightning-layout>  
    </lightning-card>
</template>

In JS Controller, import createMessageContext, subscribe, and unsubscribe methods from scoped lightning/messageService module. Also import message channel in textMessageChannel variable using @salesforce/messageChannel/TextMessageChannel__c. Create context using createMessageContext(). Use subscribe(this.context, textMessageChannel) to subscribe which will return subscription object. Use message parameter to get the publishedText.

Pass subscription object to unsubscribe() to unsubscribe from the message channel. subscribeToTextMessage method will be used to trigger the subscribe or unsubscribe method based on the value of input toggle.

subscribeLwc.js

import { LightningElement } from 'lwc';
import { createMessageContext, subscribe, unsubscribe } from 'lightning/messageService';
import textMessageChannel from "@salesforce/messageChannel/TextMessageChannel__c";
export default class SubscribeLwc extends LightningElement {
    receivedMessage = "";
    context = createMessageContext();
    objSubscription = null;
    // Call subscribe or unsubscribe based on the input toggle value.
    toggleSubscribe(event){
        if(event.target.checked){
            this.subscribeToTextMessage();
        }else{
            this.unsubscribeToTextMessage();
        }
    }
    // To subscribe to message channel.
    subscribeToTextMessage(){
        if (this.subscription) {
            return;
        }
        this.subscription = subscribe(this.context, textMessageChannel, (message) => {
            this.handleMessage(message);
        });
    }
    // TO set the received message.
    handleMessage(message) {
        this.receivedMessage = message.publishedText;
    }
    
    // To unsubscribe from the message channel.
    unsubscribeToTextMessage() {
        unsubscribe(this.subscription);
        this.subscription = null;
    }
}

Lightning Message Service in Utility Bar using LWC

Add the above Lightning Web Component in Utility Bar as well. Please check this post to enable and add Lightning Web Component in Utility Bar.

LMS in Action

This is how our Lightning Message Service (LMS) implementation looks like:

Lightning Message Service
Lightning Message Service in Action

Please Subscribe if you don’t want to miss new implementations. Thanks!

Check below Salesforce Developer guide links to know more about the Lightning Message Service.

Lightning Message Service in Aura Component

Lightning Message Service in Lightning Web Components

Lightning Message Service in Visulforce Page

4 thoughts on “Lightning Message Service (LMS) – Future of Communication”

  1. Hi Niks,
    Thanks for sharing, its very helpful for me. I have one query.
    In above for publish you are using VF and for subscribe using lightning and web components. Is this work for below scenarios
    1. Lightning (publish) to lightning (subscribe)
    2. Lightning (publish) to Web components(subscribe)
    Can you please help me on this.

    Reply
    • Hi Ashok,
      Yes, it works for both the scenarios mentioned by you. To publish from Lighting Aura Component, first add lightning:messageChannel tag with attribute “type” and aura:id. Then just use component.find(auraid).publish(message) to publish it. Subscribe logic is already mentioned in the post. You can also check the link for LMS in Aura Components that is mentioned at the bottom of the post to know more. Thanks for reading the post.

      Reply
    • Package.xml is used to retrieve the metadata from Salesforce instance. If you want to retrieve the message channel, you can add it in a package.xml as mentioned in the link attached.

      Reply

Leave a Comment