It’s often useful to warn or alert users as a response to changes they make to a Salesforce record. We might have Apex trigger logic that examines the change being made, and determines that a warning is needed. What then? There is no standard facility to have the server-side Apex code surface a message to the user in the client. We can use AddError in our trigger logic, but that would rollback the user’s transaction - we don’t want that, we just want to pass a message along.
This post describes a simple and elegant way to accomplish this using a Lightning Web Component and a Platform Event. The solution is used as follows:
Setup
- A new Platform Event is defined - in the sample code below it is named
alertToast__e
. This event has attributes that include:- A name field (
Name__c
) to label the event with the scenario that created it - e.g. “OpportunityStageChange” - Fields for variant (
Variant__c
) and mode (Mode__c
), to control the appearance and behavior of the toast alert - Fields for title (
Title__c
) and message (Message__c
), to define the toast alert contents - A user field (
User_Id__c
) to identify the user that should receive the alert - A record field (
Record_Id__c
) to identify the record that the alert is related to
- A name field (
- The LWC is deployed to the org
Configuring an Alert
- The LWC is placed on the appropriate Lightning Record Page. A component attribute “Events” is a comma-separated list of the scenarios that the component should be listening for. The component has no HTML and is invisible on the page
- Apex or flow logic is created to fire an
alertToast__e
Platform Event when needed, with the appropriate values for the event fields.
How it Works
- The LWC is subscribed to listen for all
alertToast__e
events, using thelightning/empApi
module - When an event is received the LWC inspects its contents to check the following conditions:
- Is this event for a scenario that I am configured to listen for in my Events component “Events” attribute?
- Is the user specified in the event the same as the current user? (or blank, meaning show the alert for all users)
- Is the record specified in the event the same as the current record? (or blank, meaning show the alert for all records)
- If all of the above conditions are true, the LWC dispatches a
showToastEvent
to display the alert, based on the event’s variant, mode, title, and message fields.
Sample Code
import { LightningElement, api } from "lwc";
import { subscribe, unsubscribe, onError } from "lightning/empApi";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import USER_ID from "@salesforce/user/Id";
export default class AlertToast extends LightningElement {
@api
events;
@api
recordId;
subscription;
channelName = "/event/alertToast__e";
connectedCallback() {
onError((error) => {
console.log("Received error from server: ", JSON.stringify(error));
});
let that = this;
const messageCallback = function (response) {
if (
that.events &&
that.events.split(",").includes(response.data.payload.Name__c) &&
(response.data.payload.User_Id__c === USER_ID.substring(0, 15) || response.data.payload.User_Id__c == null) &&
(response.data.payload.Record_Id__c === that.recordId || response.data.payload.Record_Id__c == null)
) {
that.dispatchEvent(
new ShowToastEvent({
title: response.data.payload.Title__c,
message: response.data.payload.Message__c,
variant: response.data.payload.Variant__c,
mode: response.data.payload.Mode__c,
})
);
}
};
if (subscription == null) {
subscribe(this.channelName, -1, messageCallback).then((response) => {
this.subscription = response;
});
}
}
disconnectedCallback() {
unsubscribe(this.subscription);
}
}
Final Thoughts
Note that Platform Events, on which this solution depends, are not a limitless resource. Information on Platform Event limits are described here, and careful consideration is needed before deploying a solution of this type in a large org, or for common scenarios.