Reputation: 3
I have tooltip custom directive. Is working as I expected, only when I use beforeUpdate hooks, not working on update hooks. The problem is that is creating multiple element when I hovering on h1 where I'm using mouseover and mouseleve.
There is some way that it will not create multiple elements?
As I'm beginner on custom directive I'll appreciate any of your help.
<div class="tooltip"><h1>Hello world from html</h1></div>
<div class="tooltip"><h1>Hello world from html</h1></div>
<div class="tooltip"><h1>Hello world from html</h1></div>
<div class="tooltip"><h1>Hello world from html</h1></div>
tooltip.ts
const updateTooltip = (el: HTMLElement, value: DirectiveBinding["value"], modifiers: DirectiveBinding["modifiers"], arg: DirectiveBinding["arg"], vnode: VNode): void => {
if (!value.text) {
el.classList.remove("tooltip-parent")
}
if (value.text) {
tooltipDiv.classList.add("tooltip")
tooltipDiv.innerHTML = value.text
el.appendChild(tooltipDiv)
}
if (value.displayArrow) {
el.style.setProperty(Tooltip.arrowDisplay, "inline")
argTooltip?.style.setProperty(Tooltip.arrowDisplay, "inline")
}
tooltipPlacement(value, el, argTooltip, argTooltipDiv)
}
export const tooltip = {
mounted: (el: HTMLElement, { value, modifiers, arg }: DirectiveBinding): void => {
if (typeof value === "object" && value.text) {
el.classList.add("tooltip-parent")
}
if (typeof value === "string" && value) {
el.classList.add("tooltip-parent")
}
updateTooltip(el, value, modifiers, arg)
},
beforeUpdate: (el: HTMLElement, { value, modifiers, arg }: DirectiveBinding): void => {
updateTooltip(el, value, modifiers, arg)
},
}
tooltipPlacement.ts
export const tooltipPlacement = (value: DirectiveBinding["value"], el: HTMLElement, argTooltip: HTMLElement, argTooltipDiv: HTMLDivElement) => {
if (value.theme) {
for (const [key, val] of Object.entries(value.theme) as [string, any][]) {
switch (key) {
case "hide":
watch(
() => val,
() => {
if (val) {
argTooltip?.style.setProperty(Tooltip.opacity, "0")
argTooltip?.style.setProperty(Tooltip.visibility, "hidden")
/**** arrow ****/
argTooltip?.style.setProperty(Tooltip.arrowOpacity, "0")
argTooltip?.style.setProperty(Tooltip.arrowVisibility, "hidden")
}
if (!val) {
console.log("show")
argTooltip?.style.setProperty(Tooltip.opacity, "1")
argTooltip?.style.setProperty(Tooltip.visibility, "visible")
/**** arrow ****/
argTooltip?.style.setProperty(Tooltip.arrowOpacity, "1")
argTooltip?.style.setProperty(Tooltip.arrowVisibility, "visible")
}
},
{ immediate: true },
)
break
default:
break
}
}
}
}
Template
<template>
<div>
<div class="p-6 centered flex-col space-y-6">
{{ !!hideTooltip }}
<h1>Tooltip</h1>
<br />
<p v-tooltip:actions.arrow="tooltipContent(html, tooltipTheme, true)" class="border w-40 h-20 text-center">hello world</p>
</div>
<div class="p-6 centered flex-col space-y-6">
<h1 class="h-20" @mouseover="hideTooltip = false" @mouseleave="hideTooltip = true">Actions</h1>
<br />
<p class="h-60 border px-4 actions">Test of args tooltip</p>
<button class="mt-10 p-6" @click="hideTooltip = !hideTooltip">{{ hideTooltip ? "Show Tooltip" : "Hide" }}</button>
</div>
</div>
</template>
Script
<script lang="ts" setup>
import { tooltipContent, ThemeOptions } from "../directives/tooltip"
import { ref, computed } from "vue"
const hideTooltip = ref(true)
const html = ref("<h1>Hello world from html</h1>")
const tooltipTheme = computed((): ThemeOptions => {
return {
placement: "leftTop",
argTxt: html.value,
hide: !!hideTooltip.value,
maxWidth: "300px",
}
})
</script>
Upvotes: 0
Views: 228
Reputation: 3
By adding the following code, it fixed the issue
const hasTooltipClass = el.querySelector(".tooltip") as HTMLDivElement
if (!hasTooltipClass) {
tooltipDiv.classList.add("tooltip")
tooltipDiv.innerHTML = value
el.appendChild(tooltipDiv)
}
Upvotes: 0