In Vue 3, the v-model
is a directive that is used for creating two-way data binding. Normally, we use this directive to bind any HTML form element with a variable to collect the input value.
But often we need to bind with a form element, that is present in a different component. In this case, you have to use a v-model
to custom components.
In this way, you can bind a variable with an HTML element that is inside a child component.
In the latest version of Vue i.e. Vue 3, we have to follow different rules than we used to follow in Vue 2.
In this article, I will show you the best possible way to add the v-model
directive to custom components in Vue 3 very easily.
If you are using Vue 2, you can follow our other post on how to add v-model to custom components in Vue2.
How Does v-model Work in Vue 3?
As you know, we use v-model
to bind a variable and a form element like input
, textarea
, and select
together so that if you change the value in one place it also changes in another one.
But to implement v-model
to custom components, have to know how this directive works in the background.
When we add v-model
in an input
field, Vue automatically adds two things behind the scene to that input.
- Vue bind the
value
attribute of that input field with the variable we provide inv-model
. - Vue adds the JavaScript
input
event to that input field so that every time users write or remove something in the input field that event fires.
This is exactly what you have to do if you want to use v-model
to custom components in Vue 3.

Use Vue 3 v-model in Custom Components
To add v-model
support to a custom component, there are 3 simple steps:
- Step 1: Add a
modelValue
prop to the component as a string. - Step 2: Register a
update:modelValue
event in the component. - Step 3: Emit
update:modelValue
event when the input value changes.
You have to use the same prop and event names. They are case-sensitive. Later, I will show you how you can use different prop and event names with a component.
But before that let's discuss each step in detail with examples. Here I will create a BaseInput.vue
component.
<!-- App.vue component -->
<template>
<base-input v-model="content"></base-input>
</template>
When I use this component inside my App.vue
component, I want to use v-model
directive. At this moment, this attribute won't do anything.
With the previously discussed 3 steps, you can add the support for this attribute to the BaseInput.vue
component.
Step 1: Add modelValue Prop to The Component
SFC (Single File Components) syntax is added in the latest version of Vue 3. Using this syntax, you can write clean and readable code inside your component.
<!-- BaseInput.vue component -->
<script setup>
const props = defineProps({
modelValue: String
})
</script>
You can define the modelValue
prop as a String by calling the defineProps()
method. You don't have to import this method. All Vue components have access to it by default.
Step 2: Register update:modelValue Event in The Component
Call the defineEmits()
method to register the update:modelValue
event in the BaseInput.vue
component.
Like defineProps()
method, you don't have to import it from Vue. Your component can access this method automatically.
<!-- BaseInput.vue component -->
<script setup>
const emit = defineEmits(['update:modelValue'])
</script>
Pass an array of the event names as strings to this method. It will register those events so that this component can emit them.
Step 3: Emit update:modelValue Event When The Value Changes
After adding the prop and event in our BaseInput.vue
component, its time to use them and emit the update:modelValue
event when the prop value changes.
<!-- BaseInput.vue component -->
<template>
<div>
<input type="text" :value="modelValue" @input="updateValue" />
</div>
</template>
<script setup>
const props = defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
const updateValue = (event) => {
emit('update:modelValue', event.target.value)
}
</script>
I am binding the modelValue
prop to the value property in my <input>
tag. When someone types in the <input>
field, the updateValue()
method will run.
It will emit the update:modelValue
event with the input value. With these 3 steps, we have added support for v-model
attributes in our BaseInput.vue
component.
Also Read: Improve Performance in Vue 3 Using Lazy Loading and Dynamic Import
Add v-model in Custom Components with setup() Function
If you are using the composition API setup()
function in your component, you can follow this method to add v-model
support to a custom component.
<!-- BaseInput.vue component -->
<template>
<div>
<h2>Composition API</h2>
<input type="text" :value="modelValue" @input="updateValue" />
</div>
</template>
<script>
export default {
props: {
modelValue: ''
},
setup(props, context) {
const updateValue = (event) => {
context.emit('update:modelValue', event.target.value);
}
return { updateValue }
}
}
</script>
In composition API, we have to use the same prop name and emit the same event as the options API.
You just have to follow the composition API syntax in your component.
In this component, I have used the setup()
function that is required for composition API.
<!-- App.vue component -->
<template>
<base-input v-model="content"></base-input>
</template>
Now you can use the BaseInput
component in any other components and apply the v-model
directive to it.
Also Read: Composition API VS Options API in Vue 3 For Beginners
Add v-model to Custom Components with Options API
Even if you don't use Vue 3 composition API, you can follow the same steps to add support for v-model
directive in your components.
<!-- BaseInput.vue component -->
<template>
<div>
<h2>Options API</h2>
<input type="text" :value="modelValue" @input="updateValue" />
</div>
</template>
<script>
export default {
props: {
modelValue: ''
},
methods: {
updateValue(event) {
this.$emit('update:modelValue', event.target.value);
}
}
}
</script>
As you can see, it doesn't matter which syntax you are using in your components. You can use the same prop and event names.
Customizing v-model Default Prop and Event Names
As of now, we have used the same prop name as modelValue
and the same event name as update:modelValue
. But what if you want to use different names?
Now I will show you how you can use a different name for prop
and event
when you usev-model
to custom components.
<!-- BaseInput.vue component -->
<template>
<div>
<h2>Custom name for Prop and Event</h2>
<input type="text" :value="title" @input="updateTitle" />
</div>
</template>
<script setup>
const props = defineProps({
title: String
})
const emit = defineEmits(['update:title'])
const updateTitle = (event) => {
emit('update:title', event.target.value)
}
</script>
In the above example, I have used title
as my prop name, which is added to the :value=""
attribute.
Now you can emit update:title
event whenever a user enters something in the input field. I am using update:title
because my prop name is title
. If you use another name, you just have to add that name with the prefix update:
.
<!-- App.vue component -->
<template>
<base-input v-model:title="postTitle"></base-input>
</template>
When you apply v-model
to that component, you must mention the prop
name that you have used in the BaseInput.vue
component.
Also Read: watch VS watchEffect in Vue 3 - Must Know Differences
Multiple Vue 3 v-model in a Custom Component
In Vue 2, we were allowed to use v-model
only once in a component.
But in Vue 3, we can attach multiple v-model
to a component at the same time. This is how you can use multiple v-model
to custom components.
<!-- BaseInput.vue component -->
<template>
<div>
<h2>Title</h2>
<input type="text" :value="title" @input="updateTitle" />
<h2>Content</h2>
<input type="text" :value="modelValue" @input="updateContent" />
</div>
</template>
<script setup>
const props = defineProps({
title: String,
modelValue: String
})
const emit = defineEmits(['update:title', 'update:modelValue'])
const updateTitle = (event) => {
emit('update:title', event.target.value)
}
const updateContent = (event) => {
emit('update:modelValue', event.target.value)
}
</script>
In the above example, I have used a custom prop
name and a custom event
name for one v-model
directive.
For another one, I will use the default names. But you can set custom names for both of them if you want.
All you have to remember is that in your event name, you will add the prop
name with the prefix update:
.
<!-- App.vue component -->
<template>
<base-input v-model="content" v-model:title="postTitle"></base-input>
</template>
When you use BaseInput.vue
component, you have to mention two v-model
directives at the same time.
In this case, you will attach the custom prop name with one v-model
. For the default name, you don't need to add anything to it.
Conclusion
I have shown you the best ways to apply the v-model
directive to Vue 3 your components. You have learned to do this using options API, composition API, and SFC script setup.
Whatever syntax you follow to create your component, now we will be able to use the v-model
to components in Vue 3 projects.