Close modal popup while clicking outside of popup in Svelte
Asked Answered
A

4

8

I have the popup modal in one of my app. I would like to close this popup while clicking outside of modal. I can achieve this behaviour using JavaScript but I can't quite find a way to make this work using Svelte framework. For now I'm achieving that behaviour like this

if (e.target.classList.contains('my-modal')){
    e.target.style.display="none";
}

but I would like to have this worked using Svelte.

Aulos answered 12/3, 2018 at 4:18 Comment(0)
V
15

A common way to solve this is to have a background element behind the modal that covers the screen and intercepts click events: https://svelte.technology/repl?version=1.57.1&example=modal-with-slot

This is also a good way to (for example) fade out the background to make the modal more visible.

Another approach is to use the special <:Window> component to listen for clicks, and stop the propagation of any clicks that begin inside the modal: https://svelte.technology/repl?version=1.57.1&gist=ba5f8a78263f2cdfbc16b1ae8732da5d

<:Window on:click='set({ message: "clicked outside the box" })'/>

<div class='clickzone' on:click='event.stopPropagation()'>
  <div class='inner' on:click='set({ message: "clicked inside the box" })'>
    {{message}}
  </div>
</div>
Voluble answered 12/3, 2018 at 12:6 Comment(2)
You can also use on:click|stopPropagation for a shorter syntaxInfrared
My working code looks like: <div class="modal" on:click={(e)=> hide()}> <div class="modal-content" on:click|stopPropagation>Infrared
H
3

For anyone reading this in 2023 or later, the syntax has been updated to <svelte:window /> instead of <:window />.

<svelte:window on:click='set({ message: "clicked outside the box" })' />
Hausfrau answered 14/3, 2023 at 17:28 Comment(0)
M
2

Check out this repo for on:outclick event: https://github.com/babakfp/svelte-outclick

Monetta answered 14/10, 2021 at 16:25 Comment(0)
F
1

You just need to add the "onclick" handler on the root div:

<div class="modal" tabindex="-1" on:click={ () => send('CLOSE') }>

I use XState to send the 'CLOSE' event to the state machine, on another examples where people just use a flag variable you can do like this:

<script>
  export let open = false;
  export let onClosed;

  const modalClose = () => {
    open = false;
    if (onClosed) {
      onClosed();
    }
  }
</script>

{#if open}
  <div class="modal" on:click={modalClose} >
  ...

I didn't have to add the stopPropagation flag on the internal buttons as I think Svelte manage automatically, but just in case you need it, inside your modal on:click logic you can add the flag: on:click|stopPropagation

<div class="modal-footer">
  <button type="button" class="btn btn-secondary" on:click={modalClose}>
    Close
  </button>
  <button type="button" class="btn btn-primary" on:click|stopPropagation={yourSaveLogic()}>
    Save changes
  </button>
</div>
Fredrick answered 5/7, 2022 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.