rabin
rabin

Reputation: 270

Close modal popup while clicking outside of popup in Svelte

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.

Upvotes: 8

Views: 7761

Answers (4)

Kyrre Gjerstad
Kyrre Gjerstad

Reputation: 51

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" })' />

Upvotes: 3

babakfp
babakfp

Reputation: 334

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

Upvotes: 2

Carlos Verdes
Carlos Verdes

Reputation: 3147

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>

Upvotes: 1

Rich Harris
Rich Harris

Reputation: 29605

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>

Upvotes: 15

Related Questions