JAVASCRIPT

Implementing a Custom v-ClickOutside Directive in Vue 3

Discover how to create a custom Vue 3 directive like `v-click-outside` to easily detect clicks that occur outside a specified element, perfect for dismissing dropdowns or popovers.

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

export default clickOutside

// main.js (or a plugin file)
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')

// components/DropdownMenu.vue
<template>
  <div class="dropdown-wrapper">
    <button @click="toggleDropdown">Toggle Dropdown</button>
    <div v-if="showDropdown" v-click-outside="hideDropdown" class="dropdown-menu">
      <p>Dropdown Item 1</p>
      <p>Dropdown Item 2</p>
      <p>Dropdown Item 3</p>
    </div>
  </div>
</template>

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

const showDropdown = ref(false)

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

const hideDropdown = () => {
  showDropdown.value = false
}
</script>

<style scoped>
.dropdown-wrapper {
  position: relative;
  display: inline-block;
}
.dropdown-menu {
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  padding: 12px 16px;
  z-index: 1;
  border-radius: 5px;
  margin-top: 5px;
}
</style>
How it works: This snippet demonstrates how to create and register a custom `v-click-outside` directive in Vue 3. The directive defines `mounted` and `unmounted` hooks, attaching and detaching a global click event listener respectively. When a click occurs, it checks if the clicked target is outside the element the directive is bound to. If so, it executes the expression provided to the directive (e.g., `hideDropdown`). This is particularly useful for UI components like dropdowns, modals, or popovers that need to be dismissed when the user clicks anywhere else on the page.

Need help integrating this into your project?

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

Hire DigitalCodeLabs