Search code examples
vue.jsvuejs3vue-composition-apiv-modelvue-script-setup

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

  • Version >= 3.3 (stable in version 3.4)

    You can directly use defineModel macro (stable in v3.4):

    Child.vue :

    <script setup>
    const modelValue = defineModel()
    </script>
    
    <template>
      <input v-model="modelValue" />
    </template>
    

    Version < 3.3

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

    Parent.vue

    <Child v-model="name" label="Name" />

    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>