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
andtextarea
elements use thevalue
attribute andinput
event- checkboxes and radio buttons use
checked
property andchange
event - select fields use
value
attribute andchange
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
.