Friday, 18 October 2019

Lightning Message Service (LMS) | MessageChannel

In Winter 20 Salesforce Introduce the new feature Lightning Message Service. 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.
  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

 

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.
Lightning Message Service LMS and Message Channel


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>

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.

 

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>

  • "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);
     }

}
  • 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>


Reference:

Some other related post:
  1. Event Communication in Lightning Web Components
  2. Event Communication in Lightning Components
  3. Setup VsCode for Salesforce
  4. Lightning We Components

Thanks
Amit Chaudhary


4 comments:

  1. Hi Amit
    Thanks for sharing this.I have followed your steps but I am facing an issue while deploying messageChannel to my devorg . Here is my error message -force-app/main/default/messageChannels/MyMessageChannel.messageChannel-meta.xml Not available for deploy for this organization
    I have checked my api version, it is 47.0 .
    Any help would be appreciated.
    Thanks
    Ashwin

    ReplyDelete
    Replies
    1. It's not GA yet outside of Dev Orgs and Scratch Orgs: https://developer.salesforce.com/docs/atlas.en-us.222.0.api_meta.meta/api_meta/meta_lightningmessagechannel.htm

      Delete
  2. I hope you added below tag in package.xml
    LightningMessageChannel

    ReplyDelete
    Replies
    1. Yes, added 'LightningMessageChannel' in package.It works in personal dev sandbox, not sure why it is not working my work sandbox.Can we use 'LightningMessageChannel' in lightning communities ?

      Delete