Two-Way Data Binding in Vue With v-model

Jul 3, 2019

Two way data binding is a powerful pattern for building JavaScript forms with Vue. For example, suppose you have an input element and a JavaScript variable value. Two way data binding means:

  1. When the user types in the input, value gets updated to match the value in input.
  2. When you update value, the input element's content updates to match value.

Vue supports two way data binding via the v-model property. In the below example, if you type in the input, Vue will display your changes in the h1 element. Also, if you update value by clicking the "Reset" button, Vue will display the new value in the input and h1 elements.

const app = new Vue({
  data: () => ({ value: 'Hello, World' }),
  template: `
    <div id="rendered-content">
      <h1>{{value}}</h1>
      <div>
        <input v-model="value"></input>
      </div>
      <button v-on:click="value = 'Hello, World'">
        Reset
      </button>
    </div>
  `
});

Here's a live example.

With Checkboxes and Dropdowns

The v-model property works seamlessly with other native inputs. If you have an input of type 'checkbox', v-model will store a boolean:

const app = new Vue({
  data: () => ({ value: false }),
  template: `
    <div id="rendered-content">
      <h1>{{value}}</h1>
      <div>
        <input type="checkbox" v-model="value"></input>
      </div>
      <button v-on:click="value = false">
        Reset
      </button>
    </div>
  `
});

Here's a live example of using v-model with checkboxes.

If you attach v-model to a select element, Vue will bind to the selected option's value.

const app = new Vue({
  data: () => ({ value: 'B' }),
  template: `
    <div id="rendered-content">
      <h1>{{value}}</h1>
      <div>
        <select v-model="value">
          <option value="A">A</option>
          <option value="B">B</option>
          <option value="C">C</option>
        </select>
      </div>
      <button v-on:click="value = 'B'">
        Reset
      </button>
    </div>
  `
});

Custom Inputs

Under the hood, v-model builds on 2 other Vue properties:

  1. v-bind to bind the input to the JavaScript value.
  2. v-on to listen for 'input' events.

You can use v-model with a custom Vue component by accepting a prop named 'value' and emitting an event named 'input'. For example, the below custom component is a fake select using div elements. Clicking on a div selects it.

Vue.component('my-select', {
  // `v-model` passes the 'value' as a prop...
  props: ['value'],
  methods: {
    set: function(v) {
      // And listens to the 'input' event for changes
      this.$emit('input', v);
    }
  },
  template: `
    <div>
      <div v-for="v in ['A', 'B', 'C']" v-on:click="set(v)">
        {{v}}
        <span v-if="v === value">[x]</span>
      </div>
    </div>
  `
});

const app = new Vue({
  data: () => ({ value: 'B' }),
  template: `
    <div id="rendered-content">
      <h1>{{value}}</h1>
      <div>
        <my-select v-model="value"></my-select>
      </div>
      <button v-on:click="value = 'B'">
        Reset
      </button>
    </div>
  `
});

Here's a live example


Vue School has some of our favorite Vue video courses. Their Vue.js Master Class walks you through building a real world application, and does a great job of teaching you how to integrate Vue with Firebase. Check it out!


Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Vue Tutorials