← Back to all snippets
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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs