It creates a mode that disables the main window but keeps it visible, with the modal window as a child window in front of it.
It forces the user to interact with it before taking action on the main Window. It is also called popup window or dialog window.
It is commonly used for scenarios like confirming a deletion, set a value.
In this post, I will demo how to create a modal window in LWC and how to extend it.
This base component is called "modalConfirmation".
It has four properties:
Title - displaying the title of popup window. i.e "Delete File?"
Message - displaying the message on popup. i.e. "Deleting a file also removes it from any records or posts it's attached to."
FirstButton - Action on the popup. ie. "Cancel".
SecondButton. - Action on the popup. i.e. "Delete"
For the button actions, I use Event to pass values to parent window, the actual process is in parent window.
1. modalConfirmation.html
This is very similar to Aura Component implementation. Lightning Design System CSS is used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <template>
<div style="height: 640px;">
<section role="dialog" tabindex="-1" aria-labelledby="heading" aria-modal="true" aria-describedby="content" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<header class="slds-modal__header">
<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
<lightning-icon icon-name="utility:close" size="medium">
</lightning-icon>
<span class="slds-assistive-text">Close</span>
</button>
<h2 class="slds-text-heading_medium slds-hyphenate">{title}</h2>
</header>
<div class="slds-modal__content slds-p-around_medium">
<center><h2><b>{message}</b></h2><br/>
</center>
</div>
<footer class="slds-modal__footer">
<lightning-button label={firstButton} variant="neutral" onclick={firstButtonAction}></lightning-button>
<lightning-button label={secondButton} variant="brand" onclick={secondButtonAction}></lightning-button>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</div>
</template>
|
2. modalConfirmation.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import { LightningElement,api } from 'lwc';
export default class ModalConfirmation extends LightningElement {
@api message;
@api title;
@api firstButton;
@api secondButton;
firstButtonAction(event)
{
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
const selectedEvent = new CustomEvent('firstbuttonclicked', { detail: this.firstButton});
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
secondButtonAction(event)
{
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
const selectedEvent = new CustomEvent('secondbuttonclicked', { detail: this.secondButton});
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
closeModal(event)
{
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
const selectedEvent = new CustomEvent('closeModal');
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
}
|
3. modalConfirmation.js-meta.xml
1 2 3 4 5 | <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>47.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle> |
4. Parentwindow.xml
Attribute openModal is used to control the display of the modal window.
Each event triggered on modalConfirmation component (onfirstbuttonclicked,onsecondbuttonclicked and onclosemodal) is bind to a method in parent window.
When DELETE button on parent window is clicked, modalConfirmation components API properties are assigned valued (Title,Message,FirstButton and SecondButton), plus openModal set to true.
This results modal window is displayed in front of the parent window.
1 2 3 4 5 6 7 | <template>
<template if:true={openModal}>
<c-modal-confirmation title={title} message={messsage} first-button={firstButton} second-button={secondButton} onfirstbuttonclicked={firstButtonClicked} onsecondbuttonclicked={secondButtonClicked} onclosemodal={closeModal}>
</c-modal-confirmation>
</template>
..................
|
5. Parentwindow.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import { refreshApex } from '@salesforce/apex';
import getContentNoteList from '@salesforce/apex/ContentNoteController.getContentNoteList';
import deleteContentNote from '@salesforce/apex/ContentNoteController.deleteContentNote';
import removeContentNote from '@salesforce/apex/ContentNoteController.removeContentNote';
import getContentNote from '@salesforce/apex/ContentNoteController.getContentNote';
export default class ContentNoteList extends LightningElement
{
@api recordId;
@api flexipageRegionWidth;
@track openModal = false;
@track messsage;
@track title;
@track firstButton;
@track secondButton;
action;
handleDeleteButton(event) {
this.action = event.detail.action.name;
this.firstButton = 'Cancel';
this.secondButton = 'Delete';
this.messsage = 'Deleting a file also removes it from any records or posts it\'s attached to.';
this.title = 'Delete File?';
this.openModal = true;
}
closeModal()
{
this.openModal = false;
}
firstButtonClicked()
{
this.openModal = false;
}
secondButtonClicked()
{
this.openModal = false;
// add your logic here
if (this.action === 'Delete')
{
}
else if (this.action ==='Remove')
{
}
}
}
|
We can also extend modalConfirmation LWC component. In the following example, we implmenet a modal datepick component.
6. modalDatePicker.html
The major part of is the same except a datepicker input component is to replace displaying a message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <template>
<div style="height: 640px;">
<section role="dialog" tabindex="-1" aria-labelledby="heading" aria-modal="true" aria-describedby="content" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<header class="slds-modal__header">
<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
<lightning-icon icon-name="utility:close" size="medium">
</lightning-icon>
<span class="slds-assistive-text">Close</span>
</button>
<h2 class="slds-text-heading_medium slds-hyphenate">{title}</h2>
</header>
<div class="slds-modal__content slds-p-around_medium">
<h2><b>
<lightning-input class="datepicker" type="date" value={selectedDate} required></lightning-input>
</b></h2><br/>
</div>
<footer class="slds-modal__footer">
<lightning-button label={firstButton} variant="neutral" onclick={firstButtonAction}></lightning-button>
<lightning-button label={secondButton} variant="brand" onclick={secondButtonAction}></lightning-button>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</div>
</template>
|
7. modalDatePicker.js
This component is inherited from modalConfirmation. We only need to add additional attributes (selectedDate in this case) and override the button action ( secondButtonAcion).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import {track } from 'lwc';
import ModalConfirmation from 'c/modalConfirmation';
export default class ModalDatePicker extends ModalConfirmation {
@track selectedDate;
secondButtonAction(event)
{
if (!this.checkComponentValidity())
return;
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
let inputComp =this.template.querySelector(".datepicker")
const selectedEvent = new CustomEvent('secondbuttonclicked', { detail: inputComp.value });
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
checkComponentValidity()
{
let inputComp =this.template.querySelector(".datepicker");
inputComp.setCustomValidity('');
if (inputComp.value)
{
let inputDate = new Date(inputComp.value);
if (inputDate < new Date())
inputComp.setCustomValidity('Invalid Date. Date Must be a Future Date.');
}
return inputComp.reportValidity();
}
}
|
8. DatePickerParentWindow.html
1 2 3 4 5 6 | <template>
<template if:true={openModalDatePicker}>
<c-modal-date-picker title='Please select a future date' first-button="No" second-button="Yes" onfirstbuttonclicked={firstDatePickerButtonClicked} onsecondbuttonclicked={secondDatePickerButtonClicked}>
</c-modal-date-picker>
</template>
|
9.DatePickerParentWindow.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import { LightningElement,wire,track } from 'lwc';
export default class DatePickerParentWindow extends LightningElement {
@track openModalDatePicker = false;
action;
openDatePicker()
{
this.openModalDatePicker = true;
}
firstDatePickerButtonClicked()
{
this.openModalDatePicker = false;
}
secondDatePickerButtonClicked(event)
{
this.openModalDatePicker = false;
//add your logic here
}
}
|
No comments:
Post a Comment