The purpose of this series is to post tips & tricks about advanced Vue concepts that can be quickly applied to every application and give you a new weapon to approach problems.
In this short article, I will explain how v-model
works and how it can be applied to every Vue component.
Understanding v-model
v-model
is a common directive used in almost every Vue application. It's typically used to enable two-way data binding on form elements and works perfectly with input
, checkbox
, select
, textarea
and radio
.
In below example, v-model
applied on the input
element binds someVal
variable with native value
property of the input.
<input v-model="someVal">
Then the directive listens for native input
event and updates someVal
every time it's emitted.
So it turns out that we can rewrite the above code to well-known events and props with the same effect:
<input
v-bind:value="someVal"
v-on:input="someVal = $event.target.value"
>
This is how v-model
applied to regular input works under the hood.
Knowing this we can use v-model
on every component that will emit input
event and accept a value
prop.
Take a look at this MagicCounter
:
<template>
<div>
<button @click="changeValue(value-1)">-</button>
<span>{{ value }}</span>
<button @click="changeValue(value+1)">+</button>
</div>
</template>
<script>
export default {
props: ["value"],
methods: {
changeValue(newVal) {
this.$emit("input", newVal);
}
}
};
</script>
Since we are emitting input
event with a new value each time it's changed and accepting the value
prop we can safely use v-model
directive on this component:
<MagicCounter v-model="count" />
Using v-model with custom components
Event thought input
and value
pair is the default setup for v-model
depending on the input type, those bindings can be different (I strongly suggest checking it's source code for details). For example in checkbox
element checked
property and change
event are used instead of default ones.
It turns out that we customize the event/prop pair accepted by v-model
directive through a model
property. For example, this is how it could look like for checkbox
element:
model: {
prop: 'checked',
event: 'change'
}
You might want to change the name of the event emitted by our MagicCounter
to be more descriptive (for example modified
).
Let’s see how we can make this custom event work with v-model
<template>
<div>
<button @click="changeValue(value-1)">-</button>
<span>{{ value }}</span>
<button @click="changeValue(value+1)">+</button>
</div>
</template>
<script>
export default {
props: ["value"],
model: {
event: `modified`
},
methods: {
changeValue(newVal) {
this.$emit("modified", newVal);
}
}
};
</script>
..and voilà! Now you know how to use v-model
with every Vue component. I hope you'll find a way to use this knowledge very soon .
Here you can find a working example with a code from the post to play with.
Stay tuned for the next parts of the series!