vue3 composition api adds or removes classes for custom input boxes

Viewed 125
<script lang="ts" setup>
import { ref, computed } from 'vue'
const { modelValue = '' } = defineProps<{
  modelValue: string
}>()
const emit = defineEmits(['update:modelValue'])

const isFilled = ref(false)

const value = computed({
  get() {
    return modelValue
  },
  set(value: string) {
    isFilled.value = value.length > 0
    emit('update:modelValue', value)
  }
})
</script>

<template>
  <input v-model="value" :class="{ 'filled': isFilled }" v-bind="$attrs" />
</template>

sfc playground

This will not take effect when the key is pressed for the first time. For example: press abcdefg, the last input box displays bcdefg, delete it with the backspace key and try again, it is still the same.

I commented out isFilled.value = value.length > 0 and it works fine, but otherwise, how can I add a class to the element?

The effect I need is to add a class named filled to it when the value of the input box is not empty.

1 Answers

I would have used a watcher for this task, example code:

<script lang="ts" setup>
import { ref, watch } from 'vue'

const { modelValue = '' } = defineProps<{
  modelValue: string
}>()
const emit = defineEmits(['update:modelValue'])
const isFilled = ref(false)
const inputText = ref("")

watch(inputText,(newValue, oldValue)=>{
  isFilled.value = inputText.value.length > 0
  emit('update:modelValue', inputText.value)
})
</script>

<template>
  <input v-model="inputText" :class="{ 'filled': isFilled }" v-bind="$attrs" />
</template>

If you just want to add the class you can do that inline aswell. example:

<script lang="ts" setup>
import { ref, watch } from 'vue'
const inputText = ref("")
</script>
<template>
  <input v-model="inputText" :class="{ 'filled': (inputText.length>0) }" v-bind="$attrs" />
</template>
Related