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 how you can add the v-model to custom components in Vue 3 very easily in the best possible way.
If you are using Vue 2, you can follow our other post on how to add v-model to custom components in Vue2.
In Vue 2, we had only one way to create a component. But in Vue 3, we can create a component in 3 different ways.
- Options API (This is old-style was available in Vue 2).
- Composition API.
- SFC (Single File Components) Script Setup.
I will show you how you can use the v-model to custom components using all three ways.
Prerequisites
Before following this article, there are some basic requirements that you need to have. These are:
- Basic knowledge about Vue 3.
- You should know about HTML form elements.
- You should know about Vue 3 directives and how to use them. ## What is Two Way Data Binding? The two-way data binding is a way to connect an HTML form element and a variable so that if the value in one place changes, it also reflects in another place. For example, if the value in the form element changes then the value stored in the variable will also change automatically at the same time.
It will also update the value in every place that variable was used in the template so that users always see the latest value.
This process is very helpful if we have to show the changes in real-time to our users. In Vue, the v-model directive uses this technique by default.
How Does v-model Work in Vue 3?
As you know, we use v-model to bind a variable and a form element 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 in v-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.
How to Add v-model to Custom Components
To add v-model support to a component, you have to do two things that the v-model directive does to an input field behind the scene.
- You have to bind the value attribute in that input field with a prop called modelValue. You must name this prop as modelValue, it is case sensitive.
- You have to listen to the input event and emit a custom event every time that input event fires. You have to name the custom event as update:modelValue, it is also case sensitive. Note: I will show you how you can use different names for prop and custom event in the later part of this article. You can use any HTML Form Element like input, select, textarea etc.
Adding v-model to Custom Components in Vue 3 Options API
In this section, I will show you how you can apply v-model to a custom component using options API.
First, you have to create a component in your Vue 3 project. I have created a component with the name BaseInput.vue, you can give any name you want.
<!-- 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>
In this component, I have an HTML input field in which I want to create two-way data binding.
Here, I have to bind the value attribute in the input field with modelValue prop and emit udpate:modelValue event.
Every time the input event fires, it runs the method updateValue. Vue automatically passes the event object to this method. And this method emits the custom event with the value user entered in the input field.
Now you can use this component in any other component and add v-model directive.
<!-- App.vue component -->
<template>
<base-input v-model="content"></base-input>
</template>
I have used the BaseInput.vue component inside App.vue component. Here, App is the parent component that has a variable called "content".
Every time someone enters something in the input field, this variable will store that value. Similarly, if you set a default value to this variable, this value will show up inside the input field.
That's how you can add v-model to custom components in Vue 3 using options API.
Adding v-model to Custom Components in Vue 3 Composition API
If you are using Vue 3 composition API 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.
Adding v-model to Custom Components in Vue 3 SFC Script Setup
SFC (Single File Components) is another syntax introduced in the latest version of Vue 3. Using this syntax, you can write clean and readable code inside your component.
<!-- BaseInput.vue component -->
<template>
<div>
<h2>SFC Script Setup</h2>
<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>
This syntax is the part of composition API. But the difference is the way we write it.
In the earlier version of Composition API, we had to use setup() function. But in the new syntax, you use the word setup in the script tag.
In the case of Props and Emits, we have to use defineProps() and defineEmits() which are provided by Vue. You don't have to even import them from Vue.
You can see it takes less code and looks a lot simple than the other two styles.
Other than that, everything is similar. Now you can import and use this component to another with the v-model directive.
<!-- App.vue component -->
<template>
<base-input v-model="content"></base-input>
</template>
Customizing v-model Default Prop and Event Names in Components
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 that 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.
Multiple v-model in a custom component in Vue 3
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.
Top comments (0)