4

I'm transitioning from Vue 2 to Vue 3 and I'm having trouble with composables. I have a bunch of components that inherits modelValue. So, for every component that uses modelValue I'm writing this code (example with a radio input component):

<script setup>
import { computed } from 'vue'

const emit = defineEmits(['update:modelValue'])
const props = defineProps({
  modelValue: {
    type: [String, null],
    required: true
  }
})

const computedValue = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})
</script>

<template>
  <label class="radio">
    <input
      v-model="computedValue"
      v-bind="$attrs"
      type="radio"
    >
    <slot />
  </label>
</template>

Is there a way to reuse the code for the modelValue?

2 Answers 2

4

For completion of @BghinC's perfect answer here the fully typed version:

Composable

File: @/composables/useModelValue.ts

import {computed} from 'vue'

export default function useModelValue<T>(
  props: {
    modelValue: T
    [key: string]: unknown
  },
  emit: (event: 'update:modelValue', ...args: unknown[]) => void
) {
  return computed({
    get: () => props.modelValue,
    set: (value: T) => emit('update:modelValue', value),
  })
}

Usage

<script setup lang="ts">
import useModelValue from '@/composables/useModelValue'

const props = defineProps<{
  modelValue: Dog
}>()

const emit = defineEmits(['update:modelValue'])

const dog = useModelValue<Dog>(props, emit)
</script>
Sign up to request clarification or add additional context in comments.

Comments

2

EDIT

I removed my previous answer as the one provided by Pascal is typed. However, for the past couple of months, a new experimental feature has been available and could help you define model values.

Here is how you could define your model value inside your component using defineModel.

<script setup lang="ts">
const modelValue = defineModel<string>()
</script>

<template>
  <input v-model="modelValue" />
</template>

You can find more information on this blog post and on the GitHub discussion.

2 Comments

This code snippet no longer seems to work. Why is that?
@WillC I removed the code snippet as it needs auto-import from Nuxt. The code still works but please test it inside a Nuxt 3 environment.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.