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
:valuedata binding - an
@inputevent 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
valueprop from the parent component - We need to copy the value of the
valueprop to a scoped variable of our component, here it'slocalValue - We setup a watcher to watch changes on the
localValuevariable 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)