To communicate between components that aren’t in the same DOM tree we can use a singleton library that follows the publish-subscribe pattern.
This is similar to Application Events in Aura Components. When we need communicate to another components which don't have any relationship(Parent/Child) with other component in a same page we will use Pub - Sub pattern.
In a publish-subscribe pattern, one component publishes an event. Other components subscribe to receive and handle the event. Every component that subscribes to the event receives the event.
Below Example will show how to pass MultipleParameters from one component to another component.
First we need to create one LightningWebComponent with name pubsub to copy pubsub.js file which is shared by Salesforce.This file mandatory to implement pub-sub model.
Copy below code into pubsub.js file and save it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A basic pub-sub mechanism for sibling component communication | |
* | |
* TODO - adopt standard flexipage sibling communication mechanism when it's available. | |
*/ | |
const events = {}; | |
/** | |
* Confirm that two page references have the same attributes | |
* @param {object} pageRef1 - The first page reference | |
* @param {object} pageRef2 - The second page reference | |
*/ | |
const samePageRef = (pageRef1, pageRef2) => { | |
const obj1 = pageRef1.attributes; | |
const obj2 = pageRef2.attributes; | |
return Object.keys(obj1) | |
.concat(Object.keys(obj2)) | |
.every((key) => { | |
return obj1[key] === obj2[key]; | |
}); | |
}; | |
/** | |
* Registers a callback for an event | |
* @param {string} eventName - Name of the event to listen for. | |
* @param {function} callback - Function to invoke when said event is fired. | |
* @param {object} thisArg - The value to be passed as the this parameter to the callback function is bound. | |
*/ | |
const registerListener = (eventName, callback, thisArg) => { | |
// Checking that the listener has a pageRef property. We rely on that property for filtering purpose in fireEvent() | |
if (!thisArg.pageRef) { | |
throw new Error( | |
'pubsub listeners need a "@wire(CurrentPageReference) pageRef" property' | |
); | |
} | |
if (!events[eventName]) { | |
events[eventName] = []; | |
} | |
const duplicate = events[eventName].find((listener) => { | |
return listener.callback === callback && listener.thisArg === thisArg; | |
}); | |
if (!duplicate) { | |
events[eventName].push({ callback, thisArg }); | |
} | |
}; | |
/** | |
* Unregisters a callback for an event | |
* @param {string} eventName - Name of the event to unregister from. | |
* @param {function} callback - Function to unregister. | |
* @param {object} thisArg - The value to be passed as the this parameter to the callback function is bound. | |
*/ | |
const unregisterListener = (eventName, callback, thisArg) => { | |
if (events[eventName]) { | |
events[eventName] = events[eventName].filter( | |
(listener) => | |
listener.callback !== callback || listener.thisArg !== thisArg | |
); | |
} | |
}; | |
/** | |
* Unregisters all event listeners bound to an object. | |
* @param {object} thisArg - All the callbacks bound to this object will be removed. | |
*/ | |
const unregisterAllListeners = (thisArg) => { | |
Object.keys(events).forEach((eventName) => { | |
events[eventName] = events[eventName].filter( | |
(listener) => listener.thisArg !== thisArg | |
); | |
}); | |
}; | |
/** | |
* Fires an event to listeners. | |
* @param {object} pageRef - Reference of the page that represents the event scope. | |
* @param {string} eventName - Name of the event to fire. | |
* @param {*} payload - Payload of the event to fire. | |
*/ | |
const fireEvent = (pageRef, eventName, payload) => { | |
if (events[eventName]) { | |
const listeners = events[eventName]; | |
listeners.forEach((listener) => { | |
if (samePageRef(pageRef, listener.thisArg.pageRef)) { | |
try { | |
listener.callback.call(listener.thisArg, payload); | |
} catch (error) { | |
// fail silently | |
} | |
} | |
}); | |
} | |
}; | |
export { | |
registerListener, | |
unregisterListener, | |
unregisterAllListeners, | |
fireEvent | |
}; |
When Call Subscriber button is clicked data will show in My Subscriber Component.Both Message and Source data will be listen from My Publisher Component.
Step1: Create publishComponent.html and save below code which contains CallSubscriber button.on click of it will the pass the predefined data to subscriberComponent.
publishComponent.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-card title="My Publisher Component"> | |
<lightning-button label="Call Subscriber" variant="brand" onclick={callSubscriber}></lightning-button> | |
</lightning-card> | |
</template> |
Step2:
=>In publishComponent.js first we need to import the pubsub component to fireEvent using below code.
import { fireEvent } from 'c/pubsub';
=>Next import the CurrentPageReference to pass the pafeRef to subscriberComponent using below code.
import { CurrentPageReference } from 'lightning/navigation';
=> Add below wire api to get the current page reference. @wire(CurrentPageReference) pageRef;
=>When button is clicked we need to fire event using below syntax.
fireEvent(this.pageRef, "typeYourEventName" , "parameter/data to pass");
=>Next import the CurrentPageReference to pass the pafeRef to subscriberComponent using below code.
import { CurrentPageReference } from 'lightning/navigation';
=> Add below wire api to get the current page reference. @wire(CurrentPageReference) pageRef;
=>When button is clicked we need to fire event using below syntax.
fireEvent(this.pageRef, "typeYourEventName" , "parameter/data to pass");
In publishComponent.js save the below code which include all the above syntax to call the subscriberComponent.
publishComponent.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-console */ | |
import { LightningElement,wire,track } from 'lwc'; | |
import { CurrentPageReference } from 'lightning/navigation'; | |
import { fireEvent } from 'c/pubsub'; | |
export default class PublishComponent extends LightningElement { | |
//@track pubMessage = "SubscriberCalled"; | |
@track pubMessage = { pubdata : "Message from Publisher", | |
source : "On Click of Button"} | |
@wire(CurrentPageReference) pageRef; | |
callSubscriber(){ | |
console.log('callSubscriber'); | |
fireEvent(this.pageRef, "pubsubEvent" , this.pubMessage); | |
} | |
} |
publishComponent.js-meta.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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__AppPage</target> | |
<target>lightning__HomePage</target> | |
<target>lightning__RecordPage</target> | |
</targets> | |
</LightningComponentBundle> |
Step4: Create subscribeComponent.html and use below to show the message from the publishComponent.
subscribeComponent.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-card title="My Subscriber Component"> | |
<h1>Message : {submessage}</h1> | |
<h1>Source : {msgSource}</h1> | |
</lightning-card> | |
</template> |
=>In subscribeComponent.js we need to import the pubsub component to register and unregister the event using below code.Add CurrentPageReference code also.
import { registerListener,unregisterAllListeners } from 'c/pubsub';
import { CurrentPageReference } from 'lightning/navigation';
=>Add below wire api to get the current page reference. @wire(CurrentPageReference) pageRef;
=>In connectedCallback life cycle hook we need to register the event to get the data using below code.
connectedCallback(){
registerListener("typeYourEventName","propertyToGetdata",this);
}
=>In disconnectedCallback life cycle hook we need to deregister the event using below syntax.
disconnectedCallback(){
unregisterAllListeners(this);
}
In subscriberComponent.js save the below code which include all the above syntax.
subscriberComponent.js
subscriberComponent.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-console */ | |
import { LightningElement,track,wire } from 'lwc'; | |
import { CurrentPageReference } from 'lightning/navigation'; | |
import { registerListener,unregisterAllListeners } from 'c/pubsub'; | |
export default class SubscribeComponent extends LightningElement { | |
@track submessage; | |
@track msgSource; | |
@wire(CurrentPageReference) pageRef; | |
connectedCallback(){ | |
registerListener("pubsubEvent",this.subscriberdata,this); | |
} | |
disconnectedCallback(){ | |
unregisterAllListeners(this); | |
} | |
subscriberdata(evtMessage){ | |
this.submessage = evtMessage.pubdata; | |
this.msgSource = evtMessage.source; | |
console.log('subEvent' + this.submessage); | |
} | |
} |
Comments
Post a Comment