How to Use v-model on Vue Component: Simple Guide
To use
v-model on a Vue component, define a modelValue prop and emit an update:modelValue event from the child component. Then, bind v-model on the component in the parent to enable two-way data binding.Syntax
Use v-model on a custom component by binding it to a prop named modelValue and emitting update:modelValue events when the value changes.
This pattern allows the parent to pass data down and listen for changes from the child.
vue
<template> <CustomInput v-model="text" /> </template> <script setup> import { ref } from 'vue' import CustomInput from './CustomInput.vue' const text = ref('') </script>
Example
This example shows a parent component using v-model with a child input component. The child receives modelValue as a prop and emits update:modelValue when the input changes.
vue
<!-- CustomInput.vue -->
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
aria-label="Custom input"
/>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script>
<!-- ParentComponent.vue -->
<template>
<CustomInput v-model="text" />
<p>You typed: {{ text }}</p>
</template>
<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'
const text = ref('Hello')
</script>Output
You typed: Hello (updates live as you type)
Common Pitfalls
- Not using
modelValueas the prop name breaksv-modelbinding. - Forgetting to emit
update:modelValueevent means the parent won't know about changes. - Using a different event name or prop requires manual
v-modelcustomization.
vue
<!-- Wrong: prop named 'value' and event 'input' (legacy) --> <template> <input :value="value" @input="$emit('input', $event.target.value)" /> </template> <script setup> const props = defineProps({ value: String }) const emit = defineEmits(['input']) </script> <!-- Right: use 'modelValue' and 'update:modelValue' --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script setup> const props = defineProps({ modelValue: String }) const emit = defineEmits(['update:modelValue']) </script>
Quick Reference
v-model on component:
- Prop name:
modelValue - Event name:
update:modelValue - Use
v-modelon component tag in parent - Emit
update:modelValuewith new value from child
| Concept | Name/Usage |
|---|---|
| Prop for value | modelValue |
| Event to emit | update:modelValue |
| Parent usage | |
| Child emits | $emit('update:modelValue', newValue) |
Key Takeaways
Always use 'modelValue' prop and 'update:modelValue' event for v-model on components.
Emit 'update:modelValue' from child to update parent data reactively.
Bind v-model on the component tag in the parent to enable two-way binding.
Avoid legacy prop/event names like 'value' and 'input' for new Vue 3 components.
Use aria-labels and semantic HTML for accessibility in custom inputs.