JAVASCRIPT

Create a `v-click-outside` Custom Directive in Vue 3

Implement a reusable Vue 3 custom directive, `v-click-outside`, to detect clicks occurring outside of a specific element, useful for dropdowns, modals, and popovers.

// directives/vClickOutside.js
const clickOutside = {
  mounted(el, binding) {
    el.__ClickOutsideHandler__ = (event) => {
      if (!(el === event.target || el.contains(event.target))) {
        if (typeof binding.value === 'function') {
          binding.value(event);
        }
      }
    };
    document.addEventListener('click', el.__ClickOutsideHandler__);
  },
  unmounted(el) {
    document.removeEventListener('click', el.__ClickOutsideHandler__);
    delete el.__ClickOutsideHandler__;
  },
};

export default clickOutside;


// main.js (Registering the directive globally)
import { createApp } from 'vue';
import App from './App.vue';
import vClickOutside from './directives/vClickOutside';

const app = createApp(App);

app.directive('click-outside', vClickOutside);

app.mount('#app');


// App.vue (Example Usage)
<template>
  <div class="page-container">
    <h1>`v-click-outside` Directive Example</h1>

    <button @click="toggleDropdown">Toggle Dropdown</button>

    <div v-if="showDropdown" v-click-outside="onClickOutsideDropdown" class="dropdown-menu">
      <p>Dropdown Content</p>
      <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
      </ul>
    </div>

    <hr>

    <button @click="toggleModal">Toggle Modal</button>

    <div v-if="showModal" class="modal-backdrop">
      <div v-click-outside="onClickOutsideModal" class="modal-content">
        <h2>Modal Title</h2>
        <p>This is some modal content. Click outside to close it.</p>
        <button @click="toggleModal">Close Modal</button>
      </div>
    </div>

  </div>
</template>

<script setup>
import { ref } from 'vue';

const showDropdown = ref(false);
const showModal = ref(false);

const toggleDropdown = () => {
  showDropdown.value = !showDropdown.value;
};

const onClickOutsideDropdown = () => {
  if (showDropdown.value) {
    console.log('Clicked outside dropdown!');
    showDropdown.value = false;
  }
};

const toggleModal = () => {
  showModal.value = !showModal.value;
};

const onClickOutsideModal = () => {
  if (showModal.value) {
    console.log('Clicked outside modal!');
    showModal.value = false;
  }
};
</script>

<style>
.page-container {
  max-width: 800px;
  margin: 50px auto;
  text-align: center;
  position: relative;
}
.dropdown-menu {
  border: 1px solid #ccc;
  padding: 10px;
  margin-top: 10px;
  background-color: white;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 100;
}
.modal-content {
  background-color: white;
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
  text-align: left;
}
</style>
How it works: This snippet demonstrates how to create and use a custom Vue 3 directive called `v-click-outside`. This directive is incredibly useful for UI elements like dropdowns, modals, or popovers that need to close when a user clicks anywhere outside of them. The `mounted` hook attaches a global click listener to the document, which checks if the click target is outside the element the directive is bound to. The `unmounted` hook ensures proper cleanup by removing the event listener to prevent memory leaks. The example shows how to apply this directive to both a dropdown and a modal component.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs