I created a svelte modal component based on this example https://svelte.dev/examples/modal
However, since I did not want the close button coming from the modal, I removed it. The code is a below
<script lang="ts">
export let showModal: boolean; // boolean
let dialog: HTMLDialogElement; // HTMLDialogElement
$: if (dialog && showModal) dialog.showModal();
</script>
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
<dialog
bind:this={dialog}
on:close={() => (showModal = false)}
on:click|self={() => dialog.close()}
class="backdrop:bg-slate-500/30 backdrop:dark:bg-slate-200/10"
>
<slot />
</dialog>
I am using this Modal in another component as below
<script lang="ts">
import Modal from '$lib/components/Modal.svelte';
let showModal = false;
</script>
<button on:click={() => (showModal = true)}> OPEN MODAL </button>
<Modal bind:showModal >
<div>cmodal content blah blah blah </div>
<button on:click={() => (showModal = false)}> CLOSE MODAL</button>
</Modal>
Modal opens without any issues whin i click the "OPEN MODAL" button but it does not close when I click "CLOSE MODAL" button! (it closes on clicking the backdrop as expected)
What I am doing wrong? How do close the modal from within the modal?
The issue is quite simple but weird:
on:click
only gets triggered when something inside the same file is being clicked, which your slot
is technically not. This means that on:click
never gets the chance to close the modal when you click the close button.on:click
is the only function that actually calls .close()
on your modal and it never gets fired, your modal can never be closed.
The solution:
Update the reactivity statement: $: {
if (dialog) {
if (showModal) {
dialog.showModal();
} else {
dialog.close();
}
}
}
It is quite simple:
This statement checks if the dialog is defined and then shows/closes the modal depending on the state of showModal
.