Easy Custom Input with defineModel in VueJS 3
Vue 3.3 introduces a new compiler macro called defineModel
that makes it easy to create custom input components with two way data binding. In this article, we will see how to create a custom input component with two way data binding in VueJS 3 using defineModel. Prior to Vue 3.3, we had to use v-model
and emit
prop update:modelValue
to achevie two way data binding for a custom component. Let’s see how to do it with defineModel.
Enable defineModel
Starting Vue 3.4 defineModel
is enabled out of the box and no changes to config are required.
If you are using Vue 3.3,
defineModel macro is still experimental and is not enabled by default and requires an explicit opt-in.To enable defineModel, you need to add the following code in vite.config.ts
file
export default {
plugins: [
vue({
script: {
defineModel: true,
},
}),
],
};
Enable defineModel in NuxtJS 3
Depending on version of NuxtJS you are using, you may need to explicitly enable defineModel. If you have Vue 3.4 as peer dependency, defineModel is enabled by default.
If you are using NuxtJS 3 with Vue 3.3, you can enable defineModel by adding the following code in nuxt.config.ts
file.
export default defineNuxtConfig({
vite: {
vue: {
script: {
defineModel: true,
},
},
},
});
Using defineModel
Let’s create a custom component called ColorPicker
that allow our user to select one of the available colors. We will use defineModel to create this custom component.
<script setup lang="ts">
const inputValue = defineModel<string>();
</script>
<template>
<div class="flex rounded-md">
<a href="#" class="border p-2 px-3" @click="inputValue = 'red'">Red</a>
<a href="#" class="border p-2 px-3" @click="inputValue = 'green'">Green</a>
<a href="#" class="border p-2 px-3" @click="inputValue = 'blue'">Blue</a>
</div>
</template>
In the above code, we have defined a inputValue
variable using defineModel. Vue will automatically create a modelValue
prop and update:modelValue
event for us. We can use inputValue
variable to set the value of the input and it will automatically update the parent component when the value changes.
Using the custom component
Let’s use the custom component we created above in our parent component.
<script setup lang="ts">
import ColorPicker from "./ColorPicker.vue";
const color = ref<string>("red");
</script>
<template>
<ColorPicker v-model="color" />
<div>Selected Color: {{ color }}</div>
</template>
defineModel
is a great addition to VueJS 3 and makes it easy to create custom input components with two way data binding. Note that this is still an experimental feature and is not enabled by default. It may change in future versions of VueJS It is available out of the box starting from Vue 3.4, you can read more about this feature in the official RFC.