JAVASCRIPT

Build a `useClickOutside` Composable in Vue 3

Learn to create a custom Vue 3 composable (`useClickOutside`) to detect clicks outside a specific DOM element, ideal for dropdowns, context menus, and popovers.

// composables/useClickOutside.js
import { onMounted, onUnmounted } from 'vue';

export function useClickOutside(targetRef, callback) {
  if (!targetRef) {
    console.warn('useClickOutside: targetRef is required.');
    return;
  }

  const handleClickOutside = (event) => {
    // Check if the click occurred outside the target element
    if (targetRef.value && !targetRef.value.contains(event.target)) {
      callback(event); // Invoke the callback if clicked outside
    }
  };

  onMounted(() => {
    // Attach the event listener when the component is mounted
    document.addEventListener('click', handleClickOutside);
  });

  onUnmounted(() => {
    // Remove the event listener when the component is unmounted to prevent memory leaks
    document.removeEventListener('click', handleClickOutside);
  });
}

// DropdownMenu.vue
<template>
  <div class="dropdown" ref="dropdownRef">
    <button @click="isOpen = !isOpen">Toggle Dropdown</button>
    <div v-if="isOpen" class="dropdown-content">
      <p>Item 1</p>
      <p>Item 2</p>
      <p>Item 3</p>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useClickOutside } from './composables/useClickOutside';

const dropdownRef = ref(null); // Create a ref to attach to the dropdown element
const isOpen = ref(false);

// Use the composable, passing the ref and a callback function
useClickOutside(dropdownRef, () => {
  if (isOpen.value) {
    isOpen.value = false; // Close the dropdown if clicked outside
    console.log('Clicked outside dropdown!');
  }
});
</script>

<style scoped>
/* Basic styling for the dropdown */
.dropdown {
  position: relative;
  display: inline-block;
  margin-top: 20px;
}
.dropdown-content {
  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;
  margin-top: 5px;
  border-radius: 4px;
}
</style>
How it works: Composables are reusable functions that encapsulate stateful logic in Vue 3's Composition API. This `useClickOutside` composable detects when a user clicks anywhere on the document outside of a specified element. It leverages `onMounted` and `onUnmounted` to properly add and remove a global click event listener, preventing memory leaks. It's ideal for implementing common UI patterns like closing dropdowns, sidebars, or modals when the user clicks away.

Need help integrating this into your project?

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

Hire DigitalCodeLabs