Adding v-model Support to Custom Vue.js Components
September 10, 2019
Overview
Almost everyone who has worked with Vue.js for few hours knows how two-way data-binding works in form elements. Below snippet shows a very basic example of this data-binding. We have used v-model
directive to bind message
from app state to the input
form element. If you change the input, the DOM (anywhere message
is used) will update itself without any explicit code written.
See the Pen pozLPjo by Mustafa Ehsan (@mustafaaloko) on CodePen.
How it works under the hood?
Any component or element which supports v-model
out of the box adheres to this contract: accept a prop named value
and emit an input
event to trigger a data change. Basically, <input v-model="message" />
is a shorthand for writing <input :value="message" @input="message = $event.target.value />"
. Below code achieves the same result as in the first example without using v-model
.
See the Pen Vue.js Data-Binding Example without v-model by Mustafa Ehsan (@mustafaaloko) on CodePen.
How to add v-model
support in custom components?
Now let’s see how we can add this support in our custom components neatly and without extra or useless code. The idea is that how we can allow our child components to modify its parent component’s state.
In our custom component, all we need to do is accept a value
prop and emit an input
event on a value change that we want to notify child component’s parent about. Any value which will be passed as the emitted event argument will be passed to parent component to maintain its state.
In the below example, we are creating a custom component named text-input
which is a re-usable custom input component we may wanna use for our project. To make sure that it operates same as HTML’s native input
element, we will add v-model
support as below:
See the Pen Custom Vue.js Component with v-model Support by Mustafa Ehsan (@mustafaaloko) on CodePen.
As shown in the above example, we are calling onInputChange
on the input
element’s value change which in turn emits the event that we discussed above. That’s it, now you can see that our custom element (<text-input v-model="message" />
) supports the v-model
directive same as our plain input elements.