You can use v-model
attribute with any of your components in Vue 3 as you use it with input elements. It will help you to create two-way data binding between components.
If you need to bind with a form element, that is present in a different component, 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.
If you are using Vue 2, you can follow our other post on how to add v-model to custom components in Vue2.
What Are We Going to Build?
We will create a BaseInput.vue
component where we will have a <input>
element. I want to bind the value of this input field with a variable from another component.
This is the complete code for the BaseInput.vue
component:
<!-- 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>
Using the BaseInput.vue
component inside the App.vue component.
<!-- App.vue component -->
<template>
<base-input v-model="content"></base-input>
</template>
Here I am using v-model
attribute with the BaseInput.vue component to bind the content
variable that is present inside the App.vue
component.
Now if you change the value of the content
variable, it will also update the <input>
field inside the BaseInput.vue
component.
And if you type something in the <input>
field, it will automatically update the content
variable.
How Does v-model Work in Vue 3?
Before implementing v-model
to custom components, you have to know how this attribute works in the background.
When we add v-model
in an input
field, Vue automatically adds two things.
- 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 your components in Vue 3.
Adding Vue 3 v-model Attribute 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: Define modelValue Prop in 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 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
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 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.