PubSub event in Lightning Web Component
Description : Event is used when we have to send some data from one component/LWC to the other.
When the relationship between two components is Parent-Child, we can send data directly using regular events, discussed in the post. But when we have the Sibling-relationships, i.e. the two components are not linked with each-other but one of them needs inputs from the other for some operations, we need the Pub-Sub (Publisher-Subscriber) event-model.
For pub-sub model to be executed, make sure both the components are on the same DOM.
--------------- pubSub.js (a stand-alone LWC) ---------------
/**
* A basic pub-sub mechanism for sibling component communication
*
* TODO - adopt standard flexipage sibling communication mechanism
when it's available.
*
* Temporarily removing all the pageRef checking in pubsub - not
supported in communities
* https://salesforce.stackexchange.com/questions/252021/
lightning-web-component-use-publish-subscribe-event-in-community-cloud
* https://gist.github.com/kmesic/262887799fb70be94707cb0b87936e7b
*/
const events = {};
/**
* 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) => {
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 = (eventName, payload) => {
if (events[eventName]) {
const listeners = events[eventName];
listeners.forEach(listener => {
try {
listener.callback.call(listener.thisArg, payload);
} catch (error) {
// fail silently
}
});
}
};
const utility = {
navigateToPage: (pageName, urlParams = "") => {
window.open(`/er/s/${pageName}?${urlParams}`, '_self');
}
};
var sharedDataForLeads = {};
export {
registerListener,
unregisterListener,
unregisterAllListeners,
fireEvent,
utility,
sharedDataForLeads
};
--------------- Sibling 1 (firing the Event) ---------------
.html -->>
<!--firing the event at some onclick/onchange event : -->
<template>
<lightning-card>
<lightning-input value={datVal} onchange={setInputVal}
label="The msg\">
</lightning-input>
</lightning-card>
</template>
.js -->>
import { LightningElement } from 'lwc';
import { fireEvent } from 'c/pubSub';
export default class PubsubFireCmp extends LightningElement {
datVal = '';
setInputVal(event){
this.datVal = event.detail.value;
fireEvent('msg', this.datVal);
//msg -> an arbitary event name
console.log(" ->> event fired ");
}
}
--------------- Sibling 2 (subscribing the Event) ---------------
.html -->>
<template>
<lightning-card>
The message is : {myMsg}
</lightning-card>
</template>
.js -->>
import { LightningElement, wire } from 'lwc';
import { CurrentPageReference, NavigationMixin } from
'lightning/navigation';
import { registerListener } from 'c/pubSub';
export default class PubsubHandleCmp extends
NavigationMixin(LightningElement) {
@wire(CurrentPageReference) pageRef;
connectedCallback() //the subscriber method to be added
inside connectedCallback method
{
registerListener('msg',this.getVal,this);
//'msg' is the same event name being fired
//getval is the method using the event data for business operations
}
myMsg = '';
getVal(val) //val is the data sent during the event
component
{
this.myMsg= val;
console.log('message '+this.myMsg);
}
}