N
Nuxt2d ago
o.m

When I click outside the modal it doesnt close. Why doesnt onClickOutside not work ?

<template>
<div
v-if="isOpen"
class="fixed inset-0 z-50 flex items-center justify-center bg-coffee-900 bg-opacity-50"
>
<div ref="modal" :class="computedModalClass" :style="styleModal">
<button
@click="closeModal"
class="absolute top-2 right-2 text-gray-500 hover:text-gray-700"
v-if="enableCloseBtn"
>
<img
src="/images/Close-Circle-Streamline-Solar.svg"
class="text-red-500"
alt="Close"
width="30"
height="30"
/>
</button>
<slot></slot>
</div>
</div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useDraggable, onClickOutside } from "@vueuse/core";

const props = defineProps({
isOpen: {
type: Boolean,
required: true,
},
modalclass: {
type: String,
required: false,
},
enableCloseBtn: {
type: Boolean,
default: true,
required: false,
},
});

const modalTarget = useTemplateRef("modal");
const modal = ref<HTMLElement | null>(null);
const styleModal = ref();
const defaultImageClass = "bg-white dark:bg-gray-800 p-4 shadow-lg";

const emits = defineEmits(["close"]);

if (modal.value) {
const { style } = useDraggable(modal, {
initialValue: {
x: (window.innerWidth - modal.value.offsetWidth) / 2,
y: (window.innerHeight - modal.value.offsetHeight) / 2,
},
});
styleModal.value = style.value;
}

const computedModalClass = computed(() => {
return props.modalclass ? props.modalclass : defaultImageClass;
});

const closeModal = () => {
emits("close");
};

onClickOutside(modalTarget.value, () => {
console.log(modalTarget.value);
closeModal();
});
</script>
<template>
<div
v-if="isOpen"
class="fixed inset-0 z-50 flex items-center justify-center bg-coffee-900 bg-opacity-50"
>
<div ref="modal" :class="computedModalClass" :style="styleModal">
<button
@click="closeModal"
class="absolute top-2 right-2 text-gray-500 hover:text-gray-700"
v-if="enableCloseBtn"
>
<img
src="/images/Close-Circle-Streamline-Solar.svg"
class="text-red-500"
alt="Close"
width="30"
height="30"
/>
</button>
<slot></slot>
</div>
</div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useDraggable, onClickOutside } from "@vueuse/core";

const props = defineProps({
isOpen: {
type: Boolean,
required: true,
},
modalclass: {
type: String,
required: false,
},
enableCloseBtn: {
type: Boolean,
default: true,
required: false,
},
});

const modalTarget = useTemplateRef("modal");
const modal = ref<HTMLElement | null>(null);
const styleModal = ref();
const defaultImageClass = "bg-white dark:bg-gray-800 p-4 shadow-lg";

const emits = defineEmits(["close"]);

if (modal.value) {
const { style } = useDraggable(modal, {
initialValue: {
x: (window.innerWidth - modal.value.offsetWidth) / 2,
y: (window.innerHeight - modal.value.offsetHeight) / 2,
},
});
styleModal.value = style.value;
}

const computedModalClass = computed(() => {
return props.modalclass ? props.modalclass : defaultImageClass;
});

const closeModal = () => {
emits("close");
};

onClickOutside(modalTarget.value, () => {
console.log(modalTarget.value);
closeModal();
});
</script>
Why doesnt the closeModal(); get called when I click outside the ref="modal" ?
2 Replies
kapa.ai
kapa.ai2d ago
Hi @o.m. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the provided code and knowledge sources, there are a few potential reasons why the onClickOutside function might not be working as expected: 1. Timing issue: The onClickOutside function is being called immediately in the setup function, but modalTarget.value might not be available yet. The ref might not be populated until after the component is mounted. 2. Incorrect ref usage: You're using both useTemplateRef and a regular ref. This might be causing confusion. To address these issues, you could try the following modifications: 1. Move the onClickOutside call into an onMounted hook to ensure the ref is available:
import { onMounted } from 'vue';

// ... other code ...

onMounted(() => {
onClickOutside(modal, () => {
console.log(modal.value);
closeModal();
});
});
import { onMounted } from 'vue';

// ... other code ...

onMounted(() => {
onClickOutside(modal, () => {
console.log(modal.value);
closeModal();
});
});
2. Use a single ref approach:
const modal = ref(null);

// In the template:
<div ref="modal" :class="computedModalClass" :style="styleModal">
const modal = ref(null);

// In the template:
<div ref="modal" :class="computedModalClass" :style="styleModal">
3. Make sure the isOpen prop is being properly controlled by the parent component. If these modifications don't resolve the issue, it's possible that there might be other factors interfering with the click detection, such as event propagation or z-index issues. For more information on using onClickOutside and other Vue 3 composables, you can refer to the VueUse documentation (https://vueuse.org/core/onClickOutside/). If the problem persists after trying these suggestions, you might want to create a minimal reproduction of the issue to help identify any other potential causes. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2d ago
<@674984670156423171> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server