VUE
Customizing v-model for Reusable Vue 3 Form Components
Explore how to implement and customize v-model on your own Vue 3 components, enabling seamless two-way data binding for custom form elements.
<!-- CustomInput.vue -->
<template>
<label>
{{ label }}
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
:placeholder="placeholder"
type="text"
/>
</label>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
defineProps({
modelValue: {
type: String,
default: ''
},
label: {
type: String,
default: 'Input Field'
},
placeholder: {
type: String,
default: 'Enter text...'
}
});
defineEmits(['update:modelValue']);
</script>
<style scoped>
label {
display: block;
margin-bottom: 10px;
}
input {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}
</style>
<!-- App.vue (example usage) -->
<template>
<div>
<h1>Custom Input Example</h1>
<CustomInput v-model="myText" label="Your Name" placeholder="Type your name here" />
<p>Value: {{ myText }}</p>
<CustomInput v-model="anotherText" label="Your Message" />
<p>Another Value: {{ anotherText }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './components/CustomInput.vue';
const myText = ref('Hello Vue 3');
const anotherText = ref('');
</script>
How it works: In Vue 3, `v-model` on a custom component expands into a `modelValue` prop and an `update:modelValue` event. This snippet demonstrates creating a `CustomInput` component that uses these conventions to support `v-model`. The `input` element binds its value to `modelValue` and emits `update:modelValue` on `@input` events, allowing seamless two-way data binding with parent components, making custom components behave like native form inputs.