Hello Trailblazers! In this post, I have explained how we can expose events from Lightning web components to the Lightning App Builder.
Please note that this is only available in the Salesforce org with Winter 2022 or greater releases. Also, it is supported only on the lightning app pages.
Why do we need to expose events to the Lightning App Builder?
In Winter 2022 release Salesforce announced the Dynamic Interactions, which means that developers can define custom events on Lightning web components and admins can add interactions to those events from Lightning App Builder, from the new Dynamic Interaction UI in the app builder.
Basically, admins can configure which other component can handle that event without code. So when the event gets fired from the source component it will update the public properties of the target component.
View all code on GitHub: Expose LWC events to Lightning App Builder
Code with example & explanation
Assume that you have a Lightning App a component showing list of Accounts. When picked you want to show the related contacts, on another component (Note that another way to achieve this is to use LMS but the Dynamic Interactions are much simpler than that).
So here is the code followed by an explanation.
Account List Component
accountList.html
<template> <div class="slds-var-p-around_xx-small slds-theme_default"> <div class="slds-var-p-around_xx-small slds-text-body_regular" if:true={wiredAccounts.error} > No data </div> <div class="slds-var-p-around_xx-small" if:true={wiredAccounts.data} > <div class="slds-text-body_regular slds-var-p-around_xx-small"> Select an Account </div> <!-- sldsValidatorIgnoreNextLine --> <lightning-datatable key-field="id" data={wiredAccounts.data} show-row-number-column columns={columnsList} max-row-selection="1" onrowselection={handleRowSelection} > </lightning-datatable> </div> </div> </template>
accountList.js
import { LightningElement, api, wire } from "lwc"; import getAccounts from "@salesforce/apex/AccountListController.getAccounts"; const ACCOUNT_COLUMNS = [ { fieldName: "Name", label: "Name" }, { fieldName: "Type", label: "Type" } ]; export default class AccountList extends LightningElement { @api apiName; @api listViewApiName; columnsList = ACCOUNT_COLUMNS; @wire(getAccounts) wiredAccounts; handleRowSelection(event) { const itemSelected = new CustomEvent("itemselected", { detail: { recordId: event.detail.selectedRows[0].Id, accountName: event.detail.selectedRows[0].Name } }); this.dispatchEvent(itemSelected); } }
accountList.js-meta.xml
<?xml version="1.0" encoding="UTF-8" ?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>53.0</apiVersion> <isExposed>true</isExposed> <masterLabel>Account List</masterLabel> <targets> <target>lightning__AppPage</target> </targets> <targetConfigs> <targetConfig targets="lightning__AppPage"> <event name="itemselected" label="Item Selected" description="This event fires when an item is selected." > <schema> { "type": "object", "properties": { "recordId": { "type": "string", "title": "Record Id", "description": "Enter an 18-digit record Id." }, "accountName": { "type": "string", "title": "Acount Name" } } } </schema> </event> </targetConfig> </targetConfigs> <description>Defines an event for an Account List component</description> </LightningComponentBundle>
Explanation of the above code
1: I have created the component AccountList
and implemented
the code to show the Accounts in a data table. Also, I have set the max row
selection to 1 so users can pick max one account from the list see
accountList.html
code above.
2: I have handled the rowselection
of the lightning data
table using the handleRowSelection
function. Which fires the event
itemselected
. Note this event name.
3: Now in the meta XML file of the component I have exposed the
event itemselected
to the lightning app builder. Note that this event
name is exactly the same as the event that we have dispatched in the
handleRowSelection
controller function.
4: Note that itemselected
event detail contains two properties
recordId
(selected account id) and accountName
(selected account
name).
handleRowSelection(event) { const itemSelected = new CustomEvent("itemselected", { detail: { recordId: event.detail.selectedRows[0].Id, accountName: event.detail.selectedRows[0].Name } }); this.dispatchEvent(itemSelected); }
5: See the target config of the component where I have exposed the event from the accountList
component to the app builder. The target config uses the same event name and property name and defines the labels and descriptions to display in the app builder.
Please note that the event name and event detail property names should be the
same as the schema defined.
<targetConfig targets="lightning__AppPage"> <event name="itemselected" label="Item Selected" description="This event fires when an item is selected." > <schema> { "type": "object", "properties": { "recordId": { "type": "string", "title": "Record Id", "description": "Enter an 18-digit record Id." }, "accountName": { "type": "string", "title": "Acount Name" } } } </schema> </event> </targetConfig>
Contact List Component
This component simply displays the list of contacts related to the selected account.
contactList.html
<template> <div class="slds-var-p-around_xx-small slds-theme_default"> <div class="slds-var-p-around_xx-small slds-text-body_regular" if:true={wiredContacts.error} > No data </div> <div class="slds-var-p-around_xx-small" if:true={wiredContacts.data} > <div class="slds-text-body_regular slds-var-p-around_xx-small"> Related Contacts of the selected account: <b>{accountName}</b> </div> <!-- sldsValidatorIgnoreNextLine --> <lightning-datatable key-field="id" data={wiredContacts.data} show-row-number-column hide-checkbox-column columns={columnsList} onrowselection={handleRowSelection} > </lightning-datatable> </div> </div> </template>
contactList.js
import { LightningElement, api, wire } from "lwc"; import getContact from "@salesforce/apex/AccountListController.getContacts"; const CONTACT_COLUMNS = [ { fieldName: "Name", label: "Name" }, { fieldName: "Email", label: "Email", type: "email" }, { fieldName: "Phone", label: "Phone", type: "phone" } ]; export default class ContactList extends LightningElement { @api recordId; @api accountName; columnsList = CONTACT_COLUMNS; @wire(getContact, { accountId: "$recordId" }) wiredContacts; }
contactList.js-meta.xml
<?xml version="1.0" encoding="UTF-8" ?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>53.0</apiVersion> <isExposed>true</isExposed> <masterLabel>Contact List</masterLabel> <targets> <target>lightning__AppPage</target> </targets> <targetConfigs> <targetConfig targets="lightning__AppPage"> <property name="recordId" type="String" label="Account Record Id" /> <property name="accountName" type="String" label="Account Name" /> </targetConfig> </targetConfigs> <description>Shows related contacts of the account</description> </LightningComponentBundle>
Apex Controller Class
public with sharing class AccountListController { @AuraEnabled(cacheable = true) public static List<Account> getAccounts(){ return [SELECT Name, Type FROM Account]; } @AuraEnabled(cacheable = true) public static List<Contact> getContacts(Id accountId){ return [SELECT Name, Email, Phone FROM Contact WHERE AccountId = :accountId]; } }
Admin Configuration
After you deploy the component creates a new app page and both components on that. Then follow the below steps to configure the Dynamic Interactions
-
Open the app builder and select the component and go to the interactions
section
-
Set the target component public property values using event properties.
- Save and activate the app.
Hi, Can you please tell me how to enable dynamic interactions in SF Org.
ReplyDeleteI'm getting "lwc/accountList/accountList.js-meta.xml: The '' tag is only supported in orgs that are enabled for Dynamic Interactions.: Source" this error.
Hi Sushil, please check if your org is in Winter 2022 release? Also, as of now Dynamic interactions are not available for record pages or home pages, only App pages are supported. So check if you are using that only on app page?
DeleteThanks for your reply and this post. Now I'm able to perform dynamic interactions.
DeleteOn click of a button, I am trying to pass 'totalPlayers' variable data to Standard Rich Text Component using Dynamic Interactions. But I keep getting error of wrong data type.
ReplyDeletePlease help
Hi Mohit, what is the data type of totalPlayers and can you show me what have you configured?
Delete