Vue during coffee break - using v-model with custom components.
Tags: javascript, vue, webdev, beginners
Published: 2019-04-08 13:13:00

---
title: Vue during coffee break - using v-model with custom components.
published: true
description: In this short article I will explain how `v-model` works and how it can be applied into every Vue component.
tags: javascript, vue, webdev, beginners
cover_image: https://cdn.pixabay.com/photo/2015/09/25/23/10/coffee-958410_1280.jpg
series: Vue during coffee break
canonical_url: https://dev.to/vue-storefront/vue-during-coffee-break-using-v-model-with-custom-components-3bo9
---
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.

````html
<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:

````html
<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` :
````html
<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:
````html
<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](https://github.com/vuejs/vue/blob/6fe07ebf5ab3fea1860c59fe7cdd2ec1b760f9b0/src/platforms/web/compiler/directives/model.js) 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:
````js
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`
````html
<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](https://codesandbox.io/s/0yo61k5zrl?fontsize=14) you can find a working example with a code from the post to play with.

Stay tuned for the next parts of the series!