Categories
JavaScript Vue

Handling Form Input with Vue.js with v-model

Spread the love

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:

  • text and textarea elements use the value attribute and input event
  • checkboxes and radio buttons use checked property and change event
  • select fields use value attribute and change as 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 .

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *