'How to use v-model on component in vue 3 script setup

I want to add a v-model on a component but I got this warning:

[Vue warn]: Component emitted event "input" but it is neither declared in the emits option nor as an "onInput" prop.

Here is my code:

// Parent.vue
<template>
  <h2>V-Model Parent</h2>
  <Child v-model="name" label="Name" />
  <p>{{ name }}</p>
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const name = ref('')
</script>
// Child.vue
<template>
  <input
    class="input"
    type="text"
    :placeholder="props.label"
    :value="props.value"
    v-on:input="updateValue($event.target.value)"
  />
</template>

<script setup>
import { defineProps, defineEmit } from 'vue'
const props = defineProps({
  label: String,
  value: String
})
const emit = defineEmit('input')

function updateValue(value) {
  emit('input', value)
}
</script>

I was trying to reproduce this tutorial but I'am stuck and got no idea what I am missing.

I want to display {{ name }} in the Parent.vue component. Do you got an idea how to solve this?



Solution 1:[1]

In vue 3 value prop has been changed to modelValue and the emitted event input to update:modelValue:

// Child.vue
<template>
  <input
    class="input"
    type="text"
    :placeholder="props.label"
    :value="props.modelValue"
    v-on:input="updateValue($event.target.value)"
  />
</template>

<script setup>

const props = defineProps({
  modelValue: String
})

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

function updateValue(value) {
  emit('update:modelValue', value)
}
</script>

Solution 2:[2]

I like to use with computed as well

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

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

const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: ''
  }
})

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

const model = computed({
  get () {
    return props.modelValue
  },

  set (value) {
    return emit('update:modelValue', value)
  }
})
</script>

Solution 3:[3]

I have the similar issues and finally I got it work. Here are one solution for one or multiple checkbox for Vue 3 and TypeScript.

solution : for one or multiple checkbox

CheckBox Component:

        <template>
          <input
            type="checkbox"
            :value="inputValue"
            :disabled="isDisabled"
            v-model="model"
            :class="[defaultClass, inputClass, checkboxClass]"
          />
        </template>
        
    <script lang="ts">
        import { defineComponent, PropType } from 'vue';
        
        export default defineComponent({
          components: {},
        
          props: {
            inputValue: {
              type: String,
              required: false,
              default: '',
            },
        
            modelValue: {
              type: [Object, Boolean] as PropType<String[] | Boolean>,
              required: false,
              default: (() => ({})) || false,
            },
        
            isDisabled: {
              type: Boolean,
              required: false,
              default: false,
            },
        
            checkboxClass: {
              type: String,
              required: false,
              default: '',
            },
          },
        
          data() {
            return {
              defaultClass: 'h-4 w-4 rounded text-primary shadow-sm',
            };
          },
        
          emits: ['update:modelValue'],
        
          computed: {
            model: {
              get() {
                return this.modelValue;
              },
              set(value) {
                this.$emit('update:modelValue', value);
              },
            },
        
            inputClass() {
              if (this.isDisabled) {
                return 'bg-dark-17 border-dark-13';
              }
              return 'bg-dark-23 border-dark-10 hover:bg-dark-25 focus:border-primary';
            },
          },
        });
        </script>

import CheckBox and use it

import CheckBox in other components;

    <div>
      <div v-for="(option, index) in options" :key="index">
        <div
          class="flex items-center justify-between p-6 py-4 border-b border-b-dark-13"
        >
          <div class="w-10">
            <Checkbox :inputValue="option.name" v-model="selectedOptions" />
          </div>
        </div>
      </div>
    </div>
    
      data() {
        return {
          selectedOptions: [],
        };
      },

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Douglas Calora
Solution 3 sherwin water