Tags:

Using event modifiers for closing modal when clicked outside

#vue #events

Jiří Procházka on October 20, 2022

It is common that modal window has semitransparent background around itself. It is called a backgrdop. Users expect the modal to be closed when clicked on this backdrop.
Here we can see how to do it just by using event modifiers without favorite click-outside directive.

Meet event modifiers

Event modifiers are litte helpers you can add to the event handling. They are:

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive

Today we are interested in .stop and .self modifiers.

.stop & .self

.stop event modifier stops event's propagation.
.self event modifier causes that the event is triggered, if the event is not from a child element (if the event.target is the element itself).

Imagine the modal with section element positioned fixed on left top of the page, with black background color and opacity 0.7. Inside of this backdrop there is a div with a white background and slot for a content.

We are handling three clicks:

  • handleBackdropClick when the backdrop is clicked
  • handleModalClick when the content of the modal is clicked
  • handleCloseBtnClick when the close button is clicked
<script>
  const show = ref(false);

  function handleBackdropClick() {
    console.log("backdrop clicked")
  }

  function handleCloseBtnClick() {
    console.log("close btn clicked")
  }

  function handleModalClick() {
    console.log("modal clicked")
  }
</script>

<button @click="show = true">Open Modal</button>

<section v-if="show" @click="handleBackdropClick" class="backdrop">
  <div class="modal" @click="handleModalClick">
    <slot></slot>
    <button @click="handleCloseBtnClick">Close</div>
  </div>
</section>

Now when we click on the backdrop we get backdrop clicked in the console.
But when we click on the content of the modal window we get modal clicked but also backdrop clicked thus we can't use the handleBackdropClick method for closing the window.
And the last one, click on the close button we get all three console statements: close clicked, modal clicked, backdrop clicked.

Using .self

When we use .self event modifier for clicking on the backdrop, we are listening the @click event only from the backdrop itself (section html element) but not from its child (the modal form itself). And it's what we want.

<script>
  const show = ref(false);

  function handleClose() {
    show.value = false;
  }
</script>

<button @click="show = true">Open Modal</button>

<section v-if="show" @click.self="handleClose" class="backdrop">
  <div class="modal">
    <slot></slot>
    <button @click="handleClose">Close</div>
  </div>
</section>

Now when we click on the content of the modal form the event doesn't bubble up and the @click on backdrop is not raised.

email-address

Subscribe to Newsletter

If you like my tips, subscribe to my newsletter to catch every article!

I won't spam you more often than once a week with an article link.

Hire Me!

I'm available for a
long-term contract

Subscribe to Newsletter

email-address

Do you like these articles?
Subscribe to my e-mail newsletter to get notified about new awesome stuff!