0
0
VueHow-ToBeginner · 4 min read

How to Use v-model with Custom Component in Vue

To use v-model with a custom Vue component, define a modelValue prop and emit an update:modelValue event when the value changes. This setup enables two-way binding between the parent and the custom component using v-model.
📐

Syntax

When using v-model on a custom component, Vue expects the component to:

  • Accept a modelValue prop which holds the current value.
  • Emit an update:modelValue event with the new value when it changes.

This allows the parent to bind data with two-way binding using v-model.

vue
<template>
  <CustomInput v-model="text" />
</template>

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

const text = ref('')
</script>
💻

Example

This example shows a custom input component that works with v-model. The parent binds a text variable to the input. When the user types, the input emits the updated value, and the parent updates automatically.

vue
<!-- CustomInput.vue -->
<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
    aria-label="Custom input"
  />
</template>

<script setup>
const props = defineProps(['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('')
</script>
Output
You typed: (shows typed text dynamically)
⚠️

Common Pitfalls

Common mistakes when using v-model with custom components include:

  • Not using the modelValue prop name, which breaks the binding.
  • Emitting events with the wrong name (must be update:modelValue).
  • Mutating the prop directly inside the component instead of emitting updates.

Always treat props as read-only and emit events to update the value.

vue
<!-- Wrong way: emits 'input' event instead of 'update:modelValue' -->
<template>
  <input
    :value="modelValue"
    @input="$emit('input', $event.target.value)"
  />
</template>

<script setup>
const props = defineProps(['modelValue'])
</script>


<!-- Right way: emits 'update:modelValue' event -->
<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

<script setup>
const props = defineProps(['modelValue'])
</script>
📊

Quick Reference

  • Prop name: modelValue
  • Event name: update:modelValue
  • Usage: <CustomComponent v-model="data" />
  • Inside component: Use defineProps(['modelValue']) and emit update:modelValue on changes.

Key Takeaways

Use the prop name 'modelValue' in your custom component to receive the bound value.
Emit 'update:modelValue' event with the new value to enable two-way binding.
Never mutate props directly; always emit events to update the parent state.
Use v-model on your custom component to bind data easily.
Follow Vue's naming conventions for smooth integration with v-model.