Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.
In this article, we’ll look at how to handle form inputs with Vue.js for the v-model directive.
Basic Usage
We can use the v-model directive to create 2-way bindings for form input, textarea, and select elements.
It gets the data from the form, sets the data in the Vue instance or component, and update the view accordingly.
It will ignore some initial value, checked or selected attributes found on form elements. It’ll treat the Vue instance data as the source of truth. Therefore, we should set the initial data in the data option of our component.
v-model uses different properties and emit different events for different input elements:
- textand- textareaelements use the- valueattribute and- inputevent
- checkboxes and radio buttons use checkedproperty andchangeevent
- select fields use valueattribute andchangeas an event
v-model doesn’t get updates during IME composition. We can listen to the input event to pick up those updates.
Text Input
A simple example is as follows:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    message: "Hello"  
  }  
});
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="message" />  
      <p>Message is {{message}}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
Then when we type something in the input box, we’ll get the same thing displayed below.
Multiline Text
It also works for multiline text. For example, we can write:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    message: "Hello"  
  }  
});
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <textarea type="text" v-model="message"> </textarea>  
      <pre>{{message}}</pre>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
Note that only v-model works for model binding, writing <textarea>{{message}}</textarea> won’t work.
Checkbox
We can use v-model on a checkbox as follows:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    checked: false  
  }  
});
index.js :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="checkbox" id="checkbox" v-model="checked" />  
      <label for="checkbox">{{ checked }}</label>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
Then when we toggle the checkbox, we’ll get true or false displayed depending on if the checkbox is checked or not.
Multiple checkboxes bound to the same model will be bound to the same array.
For instance, we can write the following:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    persons: []  
  }  
});
Note that persons must be an array.
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <label>  
        Joe  
        <input type="checkbox" v-model="persons" value="Joe" />  
      </label>  
      <label>  
        Jane  
        <input type="checkbox" v-model="persons" value="Jane" />  
      </label>  
      <label>  
        Mary  
        <input type="checkbox" v-model="persons" value="Mary" />  
      </label>  
      <p>{{ persons.join(", ") }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
In the code above, we have to bind to the same model, then we have the value attribute values populated in the persons array when the checkbox is checked.
If all 3 are checked, we get something like:
Jane, Joe, Mary
depending on the order that they’re checked.
Radio
We can also use v-model on radio buttons. To use it, we can write:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    person: ""  
  }  
});
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="radio" value="Jane" v-model="person" />  
      <label>Jane</label>  
      <br />  
      <input type="radio" value="Mary" v-model="person" />  
      <label>Mary</label>  
      <br />  
      <p>{{ person }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
Then when we click on a radio button, we get the value attribute value for the radio button displayed when it’s selected.
Select
We can use v-model on select as follows:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    selected: ""  
  }  
});
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <select v-model="selected">  
        <option disabled value="">Select One</option>  
        <option>foo</option>  
        <option>bar</option>  
        <option>baz</option>  
      </select>  
      <br />  
      <span>Selected: {{ selected }}</span>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
Then we get the selected option displayed when we select an option.
If the initial value of the v-model expression doesn’t match any options, it’ll render in an unselected state.
Multiselect also works. For instance, we can use it as follows:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    selected: []  
  }  
});
Note that it must be an array.
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <select v-model="selected" multiple>  
        <option>foo</option>  
        <option>bar</option>  
        <option>baz</option>  
      </select>  
      <br />  
      <span>Selected: {{ selected.join(', ') }}</span>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
We add the multiple attribute to the select element to allow for multiple selections. Then when we shift-click on multiple options, multiple choices will be displayed.
We can also render options dynamically as follows:
src/index.js :
new Vue({  
  el: "#app",  
  data: {  
    selected: undefined,  
    options: [  
      { text: "One", value: "one" },  
      { text: "Two", value: "two" },  
      { text: "Three", value: "three" }  
    ]  
  }  
});
index.html :
<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <select v-model="selected">  
        <option v-for="option in options" v-bind:value="option.value">  
          {{ option.text }}  
        </option>  
      </select>  
      <br />  
      <span>Selected: {{ selected }}</span>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>
The value attribute value of the select option element will be displayed.
Conclusion
We can use the v-model directive on input , textarea , and select elements.
It works on both single and multiple selection elements. When binding data to multiple selection elements, it must be bound to an array.
We can also render choices dynamically for elements with multiple choices with v-for .
