There is a stackexchange post here that is trying to make it possible for clicking outside the modal to allow the modal to close
However, I am trying to do the opposite. I have a parent component that passes data to a child component from a wire method. But whenever I click outside the modal, the modal closes and I can see a value of undefined
in the console. I'm not sure where this value is coming from since I removed all console.logs from my code to see if it was being generated somewhere else. Is there a property or a value in the LWC design system that you must include/exclude in order prevent this behavior?
I pulled this code from the following article; this is much cleaner than my implementation and the code he is using I just tested and it is still closing the modal when they click outside the modal.
HTML – Child Confirmation
<template>
<lightning-card 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 id="modal-heading-01" 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>{message}</p>
</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>
</lightning-card>
</template>
JS Child Confirmation
import {LightningElement, api} from 'lwc';
export default class ConfirmationDialog extends LightningElement {
@api visible; //used to hide/show dialog
@api title; //modal title
@api name; //reference name of the component
@api message; //modal message
@api confirmLabel; //confirm button label
@api cancelLabel; //cancel button label
@api originalMessage; //any event/message/detail to be published back to the parent component
//handles button clicks
handleClick(event){
//creates object which will be published to the parent component
let finalEvent = {
originalMessage: this.originalMessage,
status: event.target.name
};
//dispatch a 'click' event so the parent component can handle it
this.dispatchEvent(new CustomEvent('click', {detail: finalEvent}));
}
}
HTML Parent
<!-- Parent Component -->
<template>
<lightning-card title="Testing Confirmation Dialog" icon-name="custom:custom60">
<lightning-button label="Open Confirmation" slot="actions" onclick={handleClick} name="openConfirmation"></lightning-button>
<div class="slds-text-body_regular slds-p-around--small">{displayMessage}</div>
</lightning-card>
<c-confirmation-dialog title='Confirmation Title'
message='Do you want to proceed?'
confirm-label='Yes'
cancel-label='No'
visible={isDialogVisible}
original-message={originalMessage}
name="confirmModal"
onclick={handleClick}>
</c-confirmation-dialog>
</template>
JS – Parent Component
import {LightningElement, track} from 'lwc';
export default class ParentComponent extends LightningElement {
@track isDialogVisible = false;
@track originalMessage;
@track displayMessage = 'Click on the \'Open Confirmation\' button to test the dialog.';
handleClick(event){
if(event.target.name === 'openConfirmation'){
//it can be set dynamically based on your logic
this.originalMessage = 'test message';
//shows the component
this.isDialogVisible = true;
}else if(event.target.name === 'confirmModal'){
//when user clicks outside of the dialog area, the event is dispatched with detail value as 1
if(event.detail !== 1){
//gets the detail message published by the child component
this.displayMessage = 'Status: ' + event.detail.status + '. Event detail: ' + JSON.stringify(event.detail.originalMessage) + '.';
//you can do some custom logic here based on your scenario
if(event.detail.status === 'confirm') {
//do something
}else if(event.detail.status === 'cancel'){
//do something else
}
}
//hides the component
this.isDialogVisible = false;
}
}
}
Any help would be greatly appreciated. Thanks!
Best Answer
The problem with your code you have defined a custom event with name click in your child component. Basically you should not use it for your custom event. It is overriding the standard onclick behavior.
Just change the custom event name to something else:-
and handle it in parent as:-
check the working code your here:- Playground