During latest development I came for the stage that I was needed to open basic modal dialog in lightning component.
Unfortunately we cannot use most of the JQeury libraries that provide beautiful and rich dialog, therefore the solution should be using other component.
Still, this is very common request, so I thought:
1.Use 1 component that will receive parameter and will be reused in my app
2.Search in the web for solutions
I saw several good article/git and choose this A LWC Confirmation Dialog, mainly because it is simple and easy to understand.
However after several use cases, I came to the case where I needed to get also user inputs in the dialog. I searched again the web, but didn't find suitable examples, therefore I decide to expand the component that I cloned.
The solution is posted in open git lwc-dialog-with-parameters. All you need to get is the component customDialogModal, the second component is just for demo.
*Notice importance of the css file, without it if you will use input of type combobox, then the options might be invisible.
.slds-modal__content{
overflow: initial;
}
Also notice the difference input section in the code for combobox/checkbox, as it needed some other attributes vs other input types.
Full component code (can also be found in git):
html:
<template>
<template if:true={visible}>
<div class="slds-container_small">
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<header class="slds-modal__header">
<h2 data-id="titile" class="slds-text-heading_medium slds-hyphenate">{title}</h2>
</header>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<p id="data-id">{message}</p>
<template for:each={inputList} for:item="inp">
<template if:true={inp.isCombo}>
<lightning-combobox
key={inp.name}
label={inp.label}
value={inp.value}
options={inp.options}
data-keyid={inp.name}
required={inp.required}
onchange={handleInputAdded}>
</lightning-combobox>
</template>
<template if:true={inp.isInput}>
<lightning-input
value={inp.value} key={inp.name} type={inp.type} label={inp.label} data-keyid={inp.name} required={inp.required} onchange={handleInputAdded}>
</lightning-input>
</template>
<template if:true={inp.isCheckbox}>
<lightning-input
key={inp.name} type='checkbox' label={inp.label} data-keyid={inp.name} required={inp.required} onchange={handleInputAdded} checked={inp.value}>
</lightning-input>
</template>
</template>
</div>
<footer class="slds-modal__footer">
<lightning-button variant="neutral"
name="cancel"
label={cancelLabel}
title={cancelLabel}
onclick={handleClick}>
</lightning-button>
<lightning-button variant="brand"
name="confirm"
label={confirmLabel}
title={confirmLabel}
onclick={handleClick} >
</lightning-button>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</div>
</template>
</template>
js:
import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class CustomDialogModal extends LightningElement {
@api visible = false;
@api title = '';
@api name; //reference name of the component
@api message = '';
@api confirmLabel = 'Yes';
@api cancelLabel = 'No';
@api originalMessage; //any event/message/detail to be published back to the parent component
@api inputList = [];
userInput = {};
//handle button clicks
handleClick(event){
if(event.target.name == 'confirm'){
const isInputsCorrect = [...this.template.querySelectorAll('lightning-input')]
.reduce((validSoFar, inputField) => {
inputField.reportValidity();
return validSoFar && inputField.checkValidity();
}, true);
if(! isInputsCorrect){
return;
}
}
let finalEvent = {
originalMessage : this.originalMessage,
status : event.target.name
};
for(let inpItem in this.inputList){
//If user added input get it, otherwise taking the original value that was sent
finalEvent[this.inputList[inpItem].name] = this.inputList[inpItem].name in this.userInput ?
this.userInput[this.inputList[inpItem].name] :
this.inputList[inpItem].value;
}
this.dispatchEvent(new CustomEvent('modalaction', {detail : finalEvent}));
}
handleInputAdded(event){
for(let inpItem in this.inputList){
if(this.inputList[inpItem].name == event.target.dataset.keyid){
if(this.inputList[inpItem].isCheckbox == true){
this.userInput[this.inputList[inpItem].name] = event.detail.checked;
}
else{
this.userInput[this.inputList[inpItem].name] = event.detail.value;
}
}
}
}
}