Vue3 and Typescript error: Property '$el' does not exist on type 'void'. How to properly grab every tag type existing in DOM?

Issue

I am in the process of converting a Vue2 project into Vue3 and Typscript. There are plenty of bizzare errors, but I am not sure how to handle this one on $el.

I am just looking to grab every <g> tag in the template above and I can, but this error persists.

Any ideas on how to fix this?

Code sample with error

Here is the template of the component, but the entire component is too big to put on stackoverflow. I need to target the <g> tag of.

<template>
  <div class="pep-header-decoration-light">
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width="1158.942"
      height="143.376"
      viewBox="0 0 1158.942 143.376"
    >
      <g :style="`color: ${colors.green}`">
        <!-- ... -->
      </g>
      <!-- many more g elements to select here too -->
    </svg>
  </div>
</template>

Solution

As in the question Vue 3 Composition API – How to get the component element ($el) on which component is mounted, Vue 3 discourages the use of $el, since components can have more than one top-level element. Furthermore, your arrow function won’t redefine this, and this is not available in setup:

setup() itself does not have access to the component instance – this will have a value of null inside setup(). You can access Composition-API-exposed values from Options API, but not the other way around.

Given that, you should probably define a ref for either your enclosing div or your enclosing svg, and use that to get to your element:

<template>
  <div class="pep-header-decoration-light" ref="divEl">
    <svg [...]>
      <!-- ... -->
    </svg>
  </div>
</template>

Note that you’ll need to return the new ref in the object that setup returns, and that it needs the same name that it has in the template. You can access this later using this.$refs.divEl, but in the setup function you don’t have access to this to get to this.$refs.

setup(props) {
  const divEl = ref<DivElement>(); // create the ref here
  onMounted(() => {
    // no `this` and no `$el`, so use `divEl.value`
    const shapes = divEl.value.querySelectorAll("svg > g");
    // ...
  });
  // ...
  return {divEl}; // exposes the ref named `divEl`, and since it matches
                  // the template, vue will populate it during mount
}

Answered By – Jeff Bowman

Answer Checked By – Jay B. (AngularFixing Admin)

Leave a Reply

Your email address will not be published.