JAVASCRIPT
Implementing Custom `v-model` for Component Inputs
Learn how to create custom input components in Vue 3 that support the `v-model` directive, enabling two-way data binding for enhanced reusability and cleaner parent-child communication.
// components/CustomInput.vue
<template>
<label>
{{ label }}:
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</label>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
modelValue: String,
label: {
type: String,
default: 'Input',
},
});
const emit = defineEmits(['update:modelValue']);
</script>
// App.vue
<template>
<div>
<h1>Custom `v-model` Example</h1>
<p>Parent Value: {{ message }}</p>
<CustomInput v-model="message" label="Enter Message" />
<hr/>
<p>Another Parent Value: {{ anotherMessage }}</p>
<CustomInput v-model="anotherMessage" label="Another Input" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './components/CustomInput.vue';
const message = ref('Hello Vue 3!');
const anotherMessage = ref('This is a custom input.');
</script>
How it works: Vue 3's `v-model` on custom components is implemented using `modelValue` prop and `update:modelValue` event. This `CustomInput` component accepts a `modelValue` prop and emits an `update:modelValue` event whenever its internal input changes. This standard convention allows a parent component to use `v-model="message"` directly on `CustomInput`, achieving seamless two-way data binding similar to native HTML inputs.