Lightning Web Component Dialog With Inputs



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-parametersAll 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;
                }
            }
        }
    }
}






No comments:

Post a Comment

Retire of Permission on Profiles

If you are working as a Salesforce admin/developer you've probably heard somewhere that Salesforce is planning to make a significant cha...