'How to close a modal by clicking on the backdrop in Vue.js

I have created a simple reusable modal component using Vue.js and it works fine, but I want to make so that when I click on the backdrop the modal closes, how can I achieve this? I searched and found a similar question on stackoverflow: vuejs hide modal when click off of it And did the same that the accepted answer does, putting @click="$emit('close')" on the wrapper but the modal does not get closed by clicking the backdrop as it is in the provided example. Here is my code:

<template>
 <div :class="backdrop" v-show="!showModal">
      <div class="modal-wrapper">
        <div class="modal-container" :class="size"  @click="$emit('close')">
          <span class="close-x" @click="closeModal">X</span>
          <h1 class="label">{{label}}</h1>
          <div class="modal-body">
            <slot></slot>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'custom-modal',
  data() {
    return {
      showModal: false
    };
  },
  props: {
    label: String | Number,
    size: String,
    backdrop: String
  },
  components: {
    'custom-btn': customBtn
  },
  methods: {
    closeModal() {
      this.showModal = true;
    }
  }
};

</script>

<style>
.modal-wrapper {
  display: table-cell;
  vertical-align: middle;
}

.modal-container {
  margin: 0px auto;
  padding: 20px 30px;

  border-radius: 2px;
  background-color: #fff;
  font-family: Helvetica, Arial, sans-serif;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
  transition: all .3s ease;

}

.close-x {
  color: #00A6CE;
  float: right;
}

.close-x:hover {
  cursor: pointer;
}

</style>


Solution 1:[1]

Without a library you need to set it up like this:

<div class="modal-wrapper" @click="$emit('close')>
    <div class="modal-container" :class="size" @click.stop=""></div>
</div>

It looks like you're missing the @click.stop="" which is required. Additionally you want to move the $emit('close') up to the modal-wrapper level.

With a library it may be overkill, but this is something that I have used v-click-outside for.

Vue directive to react on clicks outside an element without stopping the event propagation. Great for closing dialogues, menus among other things.

Simply npm install --save v-click-outside

Then (from the docs): <div v-click-outside="onClickOutside"></div>

and:

  onClickOutside (event, el) {
    this.closeModal();
  },

Solution 2:[2]

    <template>
        <div @click="handleBackdropClick" class="backdrop" ref="backdrop">
            <div class="modal">
                <h1> Modal Title </h1>
                <input type="text" /> 
                <p> Modal Content </p>
            </div>
        </div>
    </template>
    <style>
    .modal {
        width: 400px;
        padding: 20px;
        margin: 100px auto;
        background: white;
        border-radius: 10px;
    }
    .backdrop{
        top: 0;
        position: fixed;
        background: rgba(0,0,0,0.5);
        width: 100%;
        height: 100%;
    }
    .close{
        display: none;
    }
</style>
    export default {
        methods: {
            handleBackdropClick(e){
                console.log(e)
                if (e.path[0].className == "backdrop") {
                    this.$refs.backdrop.classList.add('close');
                }
                    
            }
        }
    }
    </script>

Solution 3:[3]

Try creating a transparent div that covers all the screen but with a z-index < your modals z-index. Then @click on it, you emit your event to close the modal :) Hope it will hellp

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Pawan Kandel
Solution 3 maxshuty