Create a Base Input Form Element Vue 3
Vue 3 doesn’t come with many breaking changes relating to Vue 2, but due to it being a complete rewrite there have been one or two. These changes do provide more flexibility and power for you to use. Let’s take a look at how v-model
has changed and build a reusable BaseInput text field.
The old v-model in Vue 2
- Default v-model prop was
value
- Default v-model event was
input
The new v-model in Vue 3
- Default v-model prop is now
modelValue
- Default v-model event is now
update:modelValue
The important thing to note is whatever comes after the colon on the update:
must match the prop keyword. In this example, modelValue
is the keyword that must match.
Vue uses modelValue as the default name.
Creating the BaseInput Component
<template>
<div>
<label v-if="label" :for="id" class="font-bold block">
{{ label }}
</label>
<input
:id="id"
:type="type"
:value="modelValue"
@input="updateInput"
class="border w-full p-1"
/>
</div>
</template>
<script>
export default {
name: "BaseInput",
props: {
id: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
modelValue: {
type: [String, Number],
default: "",
},
type: {
type: String,
default: "text",
}
},
methods: {
updateInput(event) {
this.$emit("update:modelValue", event.target.value);
}
}
};
</script>
Using the BaseInput Component
Note on the BaseInput that v-model="email"
is a shorthand for:
v-model:modelValue="email"
The modelValue
relates to the prop on the BaseInput with the same name. You can change this name by using the longhand version:
v-model:myNewValue="email"
If you do want to change the name then make sure the prop and update string in your component match:
props: {
myNewValue: {
type: String,
default: "",
},
methods: {
updateInput(event) {
// update:myNewValue must match prop myNewValue
this.$emit("update:myNewValue", event.target.value);
},
},
Here is the full example of how to use the BaseInput:
<template>
<BaseInput
id="email"
class="mb-4"
type="email"
label="email"
v-model="email"
/>
</template>
<script>
import BaseInput from "./BaseInput.vue";
export default {
name: "FormComponent",
components: {
BaseInput,
},
data() {
return {
email: "",
};
},
// v-model:modelValue="email"
};
</script>