This post has been updated: https://dev.to/valentinprgnd/custom-v-model-with-vuejs-update-3han
While answering questions on Stack Overflow, one question that comes back a lot is how to wrap a form input into a Vue component and still be able to use v-model
amazing shorthand.
To answer this question, we need to understand how v-model
works first.
What is v-model
?
v-model
is syntax sugar that Vue.js provides to add to things to our component declaration:
- a
:value
data binding - an
@input
event handler
For example:
<MyComponent v-model="myVariable" />
is essentially the same as:
<MyComponent :value="myVariable" @input="(value) => myVariable = value" />
Wrapping a text input into a component
Here's a concrete example of how to wrap a basic text input into a Vue component:
<template>
<div class="custom-input">
<input v-model="localValue" placeholder="Enter your name">
</div>
</template>
<script>
export default {
name: "TextField",
props: {
value: String // 1. Receives the value as a prop
},
data() {
return {
localValue: ""
};
},
created() {
this.localValue = this.value; // 2. Copy the value in a local value variable
// Set a watcher to emit the changes to the parent component
this.$watch("localValue", value => {
this.$emit("input", value);
});
}
};
</script>
Multiple things happened here:
- We need to tell our component we are receiving a
value
prop from the parent component - We need to copy the value of the
value
prop to a scoped variable of our component, here it'slocalValue
- We setup a watcher to watch changes on the
localValue
variable and emit these changes to the parent component usingthis.$emit
FAQ
Why set the watcher?
We set up the watcher here to make sure the parent component receives the updates on the input
event (meaning when you type in the field) every time the localVariable
is updated (itself receiving the result of the input event on the input field).
Why after copying the value?
We set the watcher after the initial assignment of the value to avoid creating an infinite loop when initializing the component with a existing value (using it in an edit form for example).
Here's a code sandbox demonstrating the whole process in a small Vue app:
Top comments (0)