3

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')
2
  • Does this answer your question? Object is possibly 'null'. on a ref(null) Commented Jun 19, 2021 at 3:29
  • @StevenB. Thank you, but not quite. I just added a couple of options which seem to work, but I do not know if they are "preferred" implementations. Commented Jun 19, 2021 at 3:46

1 Answer 1

2

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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.