A modal is a type of user interface that displays content in a layer above the app. The key characteristic of a modal is that it disables the main content until the user explicitly interacts with the modal. Modals can be effective tools in UX design when used appropriately. In the Salesforce Lightning experience, modals are used for use cases like creating or editing a record, various types of messaging, and wizards. Developers often have requirements to use modals in their custom applications as well.
The Salesforce Lightning Design System (SLDS) provides a blueprint for developers needing to implement modals for their applications. However, maintaining a lot of boilerplate code has been a major pain point for developers building custom Lightning Web Components (LWCs) and wanting to utilize modals. With the Winter ’23 release, we now ship
LightningModal (see docs), a base Lightning component that makes it simpler to incorporate modals into your components.
LightningModal is based on the SLDS blueprint and follows guidelines for accessibility.
LightningModal in an application is covered extensively in the docs, and our LWC sample app, lwc-recipes, has a well-written example. In this blog post, we’ll focus specifically on modal events, which are tricky to understand. Specifically, with an example, we’ll dive deep into how to pass data from your Lightning web component to the modal component and vice versa. The aim is to help you understand how to work with the
An example use case
To understand how to pass data from your Lightning Web Component to the modal component and vice versa, we’ll explore code snippets from an example LWC app, “Mascot Explorer.” I created this app to help us learn how to use modal events.
The Mascot Picker LWC component within the Mascot Explorer app lets you pick your favorite Salesforce Mascot. Codey is what I would pick, but I will leave it up to you to choose one!
The Mascot Picker app consists of the following components.
- A LWC component named “Mascot Picker” launches the modal component.
- A LWC component named “Mascot Picker Modal” launched as a modal from the “Mascot Picker” LWC component. This component uses the
- A visual picker LWC component named “Visual Picker” is contained within the “Mascot Picker Modal” LWC component (a child of the Mascot Picker Modal LWC component). The Visual Picker component has an input form element of the type radio to allow the selection of your favorite Mascot.
The diagram below can help you visualize how various components are composed.
Creating the Mascot Picker Modal LWC component
mascotPickerModal is an LWC component launched as a modal from the Mascot Picker LWC component. It is built using the
LightningModal base component. The
The code for the
mascotPickerModal component is as below.
LightningModalas shown below.
- You can define the modal header, body, and footer using out-of-box component markups as shown in the code snippets below.
- The body of the modal in our example uses a custom LWC component,
visualPicker. This component fires a select event to indicate mascot selection. The selection event is handled by the
- When the Confirm button in the modal footer is clicked, the component dispatches a Select event. This is shown in the code snippets below. The select event is handled in the Mascot Picker LWC component covered in the next section.
Launching the Mascot Picker Modal LWC component as a modal from the Mascot Picker LWC component
The Mascot Picker Modal component we covered in the previous section is launched as a modal from the Mascot Picker LWC component. In our example, the
mascotPicker component has a
lightning-button to open the modal component.
The code snippet to launch the
mascotPickerModal LWC component as modal is shown below.
mascotPickerModal LWC component as modal from the Mascot Picker LWC component is shown below.
mascotPickerModalLWC component is imported to the Mascot Picker LWC component using a simple import statement
- To open the
mascotPickerModalLWC component as modal, use the
NOTE – The LightningModal also supports the headless variant. You can leave out the
lighnting-modal-footer.Make sure to add the ‘label’ attribute to the
.openmethod for accessibility.
- You can pass in the data from the Mascot Picker component to the
mascotPickerModalcomponent by using the
@apiproperties declared in the
The diagram below shows the flow of data between the Mascot Picker LWC component (the component that launches the modal) and the
mascotPickerModal (launched as a modal) LWC component.
- You can listen for the events in the Mascot Picker component dispatched from the
mascotPickerModalcomponent. To do this, bind the events to the
.open()method of the
mascotPickerModalcomponent’s class. This is shown in the code snippet below.
The diagram below shows how to dispatch and capture events between the Mascot Picker LWC component and the
mascotPickerModal LWC component.
NOTE – ‘oneventname’ on the left of the image and ‘eventname’ on the right is the key to naming events.
To summarize, there are two ways of moving data out of the LightningModal:
- By closing the Modal and passing the data in the
- Modal events are covered in the previous diagram.
At the time of writing this blog post, we found an issue with the
LightningModal component for those who have the Lightning Web Security (LWS) setting disabled in their orgs. The issue is that the events dispatched from the
lightning-button in the
LightningModal do not fire. The error encountered is usually shown when you debug via the Chrome developer console as:
'EventTarget': parameter 1 is not of type 'Event'.
We have a workaround for the above issue till you enable LWS setting for your org. Wrap the component within the modal that dispatches the event into its dedicated LWC component.
For our example app to work in orgs that have LWS disabled, I have created a dedicated LWC component
buttonWrapper that dispatches the custom events that can be handled in the component launching the modal. We use this wrapper component instead of the standard
lightning-button to get the modal events working.
The code for the Button Wrapper LWC component used as a child component in the
mascotPickerModal LWC component is shown below.
The component markup:
The modified component markup of the
mascotPickermodal LWC is using the new
buttonWrapper as a child component is shown below.
To see the complete working source code of the app with custom events for orgs with disabled Lightning Web Security, check out the source code in the branch, lws-disabled.
LightningModal component also comes with built-in features, such as SLDS blueprint styles, accessibility, and support for styling hooks. Read more on this in the docs. A dedicated component for building modals means less boilerplate code and improved developer efficiency.
LightningModal— component reference
- SLDS Modal Blue Print
- LWC Recipes sample app — sample app with bite-sized recipes for learning LWC
About the author
Mohith Shrivastava is a Developer Advocate at Salesforce with a decade of experience building enterprise-scale products on the Salesforce Platform. He is presently focusing on the Salesforce Developer Tools, Flow, Apex, and Lightning Web Components at Salesforce. Mohith is currently among the lead contributors on Salesforce Stack Exchange, a developer forum where Salesforce Developers can ask questions and share knowledge. You can follow him via his Twitter @msrivastav13.