Home > other >  Is there a way to reference a DOM element in Svelte component created using Client-side component AP
Is there a way to reference a DOM element in Svelte component created using Client-side component AP

Time:06-08

I am creating a svelte component in use:action function and I need to get the DOM element from the svelte component. I can't figure out how to bind or just get reference to DOM element in this scenario. One way I thought was to give the element a unique attribute, class or any identifier to use document.querySelect grab it but I feel like there should be way to get the element since I just create it right there. I am looking for api to equivalent of bind:this.

Example code

import ToolTip from '$lib/components/tooltips/Plain.svelte';

export default function (node: HTMLElement) {
  const title = node.getAttribute('title');
  let tooltipComponent = new ToolTip({
      props: {
          title,
      },
      target: node,
  });
  const tooltip = undefined; // ?? how to get the DOM element here
  let arrow = tooltip.querySelector('#tooltip-arrow');
  let update = () => {
    compute(node, tooltip, arrow);
  };
  node.addEventListener('mouseenter', update);
  node.addEventListener('focus', update);

  return {
     update() {
    },
    destroy() {
      node.removeEventListener('mouseenter', update);
      node.removeEventListener('focus', update);
      tooltipComponent.$destroy();
    },
  };
}

One way I thought to do it

  const uniqueId = generateUniqueId();
  let tooltipComponent = new ToolTip({
      props: {
          title,
          class: `tooltip-${uniqueId}`,
      },
      target: node,
  });
  const tooltip = tooltip.querySelector(`.tooltip-${uniqueId}`);

CodePudding user response:

There is no guaranteed way of finding any elements because components do not necessarily create any. Using some unique identifier or the DOM hierarchy can work if you know the structure of the component you create.

Just make sure to look within the target that you mount the component on. So use something like node.querySelector(...).

REPL example

CodePudding user response:

Alternatively to querying the element a reference inside the component could be set with bind:this and either made accessible via <svelte:options accessors={true}/> or a function REPL

<script>
    import Tooltip from './Tooltip.svelte'

    function addTooltip(node) {
        const title = node.getAttribute('title');
        const tooltipComp = new Tooltip({ target: node , props: {title}});
        const tooltipElem = tooltipComp.tooltip
        tooltipElem.style.background = 'lightblue'
        const tooltipElemFn = tooltipComp.getTooltipElem()
        tooltipElemFn.style.border = '2px solid purple'
    }
</script>

<div use:addTooltip title="tooltip">
    I have a tooltip
</div>
<svelte:options accessors={true}/>
<script>
    export let title
    
    // export variable with option accessors={true} OR make accessible via function 
    export let tooltip
    
    export function getTooltipElem() {
        return tooltip
    }
</script>

<div bind:this={tooltip}>
    {title}
</div>
  • Related