47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
// taken from https://stackoverflow.com/questions/36170425/detect-click-outside-element
|
|
import { DirectiveBinding, VNode } from 'vue';
|
|
|
|
declare global {
|
|
interface HTMLElement {
|
|
clickOutsideEvent: (event: Event) => void;
|
|
}
|
|
}
|
|
|
|
/*
|
|
todo:
|
|
there is a special interaction with nested elements where the parent has a @click event:
|
|
the parent triggers the event, something happens, but the click event bubbles to the child element.
|
|
If the event is then used to open some kind of sidebar or modal that has the `click-outside` propert, t
|
|
he bubbled event will be outside of it, thereby closing it.
|
|
|
|
example:
|
|
<div
|
|
class="sidebar"
|
|
v-if="showSidebar"
|
|
v-click-outside="showSidebar=false"
|
|
>
|
|
...
|
|
</div>
|
|
|
|
<a class="sidebar-toggle" @click="showSidebar=true">
|
|
<span>Hello</span>
|
|
</a>
|
|
|
|
FIX:
|
|
In this example, setting the event on the a-tag as `@click.stop` will solve the problem
|
|
*/
|
|
export default {
|
|
unmounted(el: HTMLElement) {
|
|
document.body.removeEventListener('click', el.clickOutsideEvent);
|
|
},
|
|
created: (el: HTMLElement, binding: DirectiveBinding) => {
|
|
el.clickOutsideEvent = (event: Event) => {
|
|
if (!(el === event.target || el.contains(event.target as Node))) {
|
|
const eventHandler = binding.value;
|
|
eventHandler(event);
|
|
}
|
|
};
|
|
document.body.addEventListener('click', el.clickOutsideEvent);
|
|
},
|
|
};
|