How to assign class to template ref? -- VueJS 3 Typescript Component API

Viewed 2123

How do I add/remove CSS classes from a template ref using the Vue 3 Composition API and typescript?

I am running into the following typescript errors for modal.value:

  1. const modal = ref(null) returns Object is possibly 'null'.
  2. const modal = ref<HTMLDivElement | undefined>() return Object is possibly 'undefined'.
<template>
    <button @click="hideModal">Hide</button>
    <div class="show" ref="modal"></div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
    ...
    setup(){
        const modal = ref(null)
        const hideModal = () => modal.value.classList.remove('show')

        return {modal, hideModal}
    }
})
</script>

These two options work, however, could someone explain if this is or is not a preferred method.

Option A:

const modal = ref()
const hideModal = () => modal.value.classList.remove('show')

Option B:

const modal = ref({})
const hideModal = () => (modal.value as HTMLDivElement).classList.remove('show')
1 Answers

DOM manipulation should be avoided because Vue will overwrite those changes if the component needs to be rerendered.

You could use a class binding instead. That would also obviate the template ref (modal) if it were only intended for modifying the element's class list:

<template>
    <button @click="hideModal">Hide</button>
    <div :class="{ show: isShown }"></div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
    setup(){
        const isShown = ref(false)
        const hideModal = () => isShown.value = true

        return { isShown, hideModal }
    }
})
</script>

If your style for the show class is only setting CSS visibility, consider using the v-show directive instead:

<div v-show="isShown"></div>

...or the v-if directive:

<div v-if="isShown"></div>
Related