Ad Code

Implement lightning message service in salesforce

Lightning message service Salesforce

Lightning message Service enables the communication between Visualforce and lightning components anywhere on the lightning page. It provides a simple API to publish messages and subscribe to it from different modules within the current DOM (Document Object Model). 

Component methods and events help in passing the data only when the components sit in the hierarchy but here, we are dealing with the components which are in the DOM but not in the hierarchy. 
Lightning Message Service lets you publish and subscribe to messages across the DOM and between Aura, Visualforce, and Lightning Web Components.

Learning objectives


Lightning message channel
Lightning Web component: Publish and subscribe
Aura Component: Publish and subscribe
Visualforce page: Publish and subscribe


1. Lightning message channel

Lightning message channel is a new type of metadata that acts as a medium to pass the data between the modules or components. At run time, you can publish and subscribe to messages on them.

You can create a new message channel in the VS Code with the below steps 

Create a new folder messageChannels in the path force-app\main\default

Create a new file inside the folder with the name accountDetails.messageChannel-meta.xml

You can replace the name accountDetails as per your requirement


Lightning message service Salesforce - vs code


Add the below code


<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel>AccountMessageChannel</masterLabel>
    <isExposed>true</isExposed>
    <description>This is a sample Lightning Message Channel.</description>
</LightningMessageChannel>



Add channel metadata details in the package.xml


<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>LightningMessageChannel</name>
    </types>
    <version>47.0</version>
</Package>



Deploy the changes to your org. Your message channel is ready to subscribe and receive published messages from any component.


2. Lightning web component

LWC Publish: lwcPublishComp

lwcPublishComp.html


<template>
    <lightning-card title="LWC Publish component" icon-name="standard:account">
        <div class="slds-m-top_small slds-p-around_medium">
            <lightning-input type="text" name="accountNumber" value={accountNum} id="accountId" onchange={onValueChange}>
            </lightning-input>  
        </div>
        <div class="slds-m-top_small">
            <lightning-button label="Publish" variant="brand" title="Contact search" onclick={publishMessage} class="slds-p-around_medium">
            </lightning-button>
        </div>
    </lightning-card>
</template>



lwcPublishComp.js



import { LightningElement, wire, track } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import accMessageChannel from '@salesforce/messageChannel/accountDetails__c';
export default class LwcPublishComp extends LightningElement {
    @track accountNum = null;
    @wire(MessageContext)
    MessageContext;

    onValueChange(event){
        if( event.target.name == 'accountNumber' ){
            this.accountNum = event.target.value;
        }
     }

    publishMessage() {
        const message = {
            recordId: this.accountNum,
            recordData: {
                source: "LWC"
            }
        }
        publish(this.MessageContext, accMessageChannel, message);
    };   
}



lwcPublishComp.js-meta.xml



<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>



Description

import { publish, MessageContext } from 'lightning/messageService';

The above-mentioned line imports messageService to the web component context. This internally refers to messageServiceInternal.js which has definitions for publish, subscribe, unsubscribe, and so forth methods needed for the lightning message service to work.

When the user changes the account number in the input textbox, the value gets mapped to the accountNum variable and when you click on the publish button this variable is added to the message, and the formatted JSON message is published over the message channel API. 


Lightning message service Salesforce debug console


You can debug the code to find out exactly how the execution moves across the different files. 

Ok, let us quickly jump to create another lightning web component to subscribe to the message. I am curious to see this as much as you.


LWC Subscribe: lwcSubscribeComp 

lwcSubscribeComp.html


<template>
    <lightning-card title="LWC subscribe component" icon-name="standard:account">
        <div class="slds-m-top_large">
            <lightning-button label="Subscribe" variant="brand" title="" onclick={subscribeMC} class="slds-m-left_small">
            </lightning-button>
            <lightning-button label="Unsubscribe" variant="brand" title="" onclick={unsubscribeMC} class="slds-m-left_medium">
            </lightning-button>
        </div>
        <div class="slds-m-top_medium slds-m-left_small">
            <span> <b>{receivedMessage}</b></span> 
        </div>
    </lightning-card>
</template>



lwcSubscribeComp.js


import { wire, LightningElement } from 'lwc';
import { subscribe, unsubscribe, MessageContext } from 'lightning/messageService';
import accMessageChannel from '@salesforce/messageChannel/accountDetails__c';
export default class LwcSubscribeComp extends LightningElement {
    @wire(MessageContext)
    messageContext;

    subscription = null;
    receivedMessage;

   subscribeMC() {
        if (this.subscription) {
            return;
        }

        this.subscription = subscribe(
            this.messageContext,
            accMessageChannel, (message) => {
                this.handleMessage(message);
            });
    }

    handleMessage(message) {
        this.receivedMessage = message ? JSON.stringify(message, null, '\t') : 'no message payload';
    }

    unsubscribeMC() {
        unsubscribe(this.subscription);
        this.subscription = null;
        this.receivedMessage = null;
    }
}



lwcSubscribeComp.js-meta.xml


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>



Well, check-in the component files to the server and have a look at the output.

Lightning message service Salesforce lwc

Great! Let us explore the same with aura and visualforce now.


3. Aura lightning component

Aura Publish: AuraPublishComponent 

AuraPublishComponent.cmp


<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="accountNum" type="String" />
    <lightning:messageChannel type="accountDetails__c"
                              aura:id="sampleMessageChannel"/>
   
    <lightning:card title="Aura Publish component" iconName="standard:account">
        <div class="slds-m-top_small slds-p-around_medium">
            <lightning:input type="text" name="accountNumber" value="{!v.accountNum}" id="accountId" onChange="{!c.onValueChange}">
            </lightning:input>  
        </div>
        <div class="slds-m-top_small slds-m-left_medium">
            <lightning:button label="Publish" variant="brand" title="Contact search" onclick="{!c.publishMessage}" class="" />
        </div>
    </lightning:card>
</aura:component>



AuraPublishComponent.js


({
    publishMessage: function(cmp, event, helper) {
        var sMsg = {
            recordId: cmp.get("v.accountNum"),
            recordData: {
                source: "Aura component"
            }
        };
       
        cmp.find("sampleMessageChannel").publish(sMsg);
    },
    onValueChange: function(cmp, event, helper) {
        var sInp = cmp.find("accountId").
        cmp.set("v.accountNum", sInp.get("v.value"));
    }
})



Aura Subscribe: AuraSubscribeComponent 

AuraSubscribeComponent.cmp


<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="recordValue" type="String"/>
    <lightning:messageChannel type="accountDetails__c"
                              onMessage="{!c.handleChanged}" scope="APPLICATION"/>
   
    <lightning:card variant="Narrow" title="Aura subscribe component" iconName="standard:account">      
        <p class="slds-p-horizontal_small">
           <b> <lightning:formattedText value="{!v.recordValue}" /> </b>
        </p>
    </lightning:card>
</aura:component>



AuraSubscribeComponent.js


({
    handleChanged: function(component, message, helper) {
        var sMsgVal = JSON.stringify(message._params);
        if (message != null && sMsgVal != null) {
            component.set("v.recordValue", sMsgVal);
        }
    }
})


Output


4. Visualforce

Visualforce Publish

VFPublishPage.vfp


<apex:page >
    <div>
        <p>Account#</p>
        <input type="text" id="MCMessageTextArea"/> <br />
        <button onclick="publishMC()">publish</button>
    </div>
    <script type="text/javascript">
    var accDetailsChannel = "{!$MessageChannel.accountDetails__c}";
    var subscriptionToMC;
    function publishMC() {
        var sAccNumber = document.getElementById('MCMessageTextArea').value;
        const payload = {
            recordId: sAccNumber,
            recordData: {source: "Visualforce page"}
        }
        sforce.one.publish(accDetailsChannel, payload);
    }
    </script>
</apex:page>



Visualforce Subscribe

VFSubscribePage.vfp


<apex:page >
    <div>
        <button onclick="subscribeMC()">Subscribe</button>
          <br/>
        <br/>
        <button onclick="unsubscribeMC()">Unsubscribe</button>
        <br/>
        <br/>
        <p>Received message:</p>
<textarea id="MCMessageTextArea" rows="8" style="width:100%;"/>
    </div>
    <script type="text/javascript">
        var sAccMessage = "{!$MessageChannel.accountDetails__c}";
        var subscriptionToMC;
        function displayDetails(message) {
            var textArea = document.querySelector("#MCMessageTextArea");
            textArea.innerHTML = message ? JSON.stringify(message, null, '\t') : 'no message payload';
        }

        function subscribeMC() {
            if (!subscriptionToMC) {
                subscriptionToMC = sforce.one.subscribe(sAccMessage, displayDetails);
            }
        }

        function unsubscribeMC() {
            if (subscriptionToMC) {
                sforce.one.unsubscribe(subscriptionToMC);
                subscriptionToMC = null;
            }
        }
    </script>
</apex:page>


Output
Lightning message service Salesforce visualforce


To make this VF page available to add it in the app builder make sure to select “Available for Lightning Experience, Lightning Communities, and the mobile app” option in the setup > Visualforce page > VFSubscribePage as shown below

Lightning message service Salesforce setup
Follow the same for Publish Visualforce Page.

We have covered publish and subscribe scenarios for each type of component in the above sections and I hope that these details will be useful for your LMS implementation. Please note that in all the methods discussed above we always published and subscribed to the same messaging channel. 

Appreciate your feedback or queries in the comments section below. stay tuned for more articles on lightning web components.

Post a Comment

0 Comments