Handling Forms

The Basics

You can use the v-model directive to create two-way data bindings on form input elements. It automatically picks the correct way to update the element based on the input type.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<form id="demo">
<!-- text -->
<p>
<input type="text" v-model="msg">
{{msg}}
</p>
<!-- checkbox -->
<p>
<input type="checkbox" v-model="checked">
{{checked ? "yes" : "no"}}
</p>
<!-- radio buttons -->
<p>
<input type="radio" name="picked" value="one" v-model="picked">
<input type="radio" name="picked" value="two" v-model="picked">
{{picked}}
</p>
<!-- select -->
<p>
<select v-model="selected">
<option>one</option>
<option>two</option>
</select>
{{selected}}
</p>
<!-- multiple select -->
<p>
<select v-model="multiSelect" multiple>
<option>one</option>
<option>two</option>
<option>three</option>
</select>
{{multiSelect}}
</p>
<p><pre>data: {{$data | json 2}}</pre></p>
</form>
1
2
3
4
5
6
7
8
9
10
new Vue({
el: '#demo',
data: {
msg : 'hi!',
checked : true,
picked : 'one',
selected : 'two',
multiSelect: ['one', 'three']
}
})

Result

{{msg}}

{{checked ? "yes" : "no"}}

{{picked}}

{{selected}}

{{multiSelect}}

data:

{{$data | json 2}}

Lazy Updates

By default, v-model syncs the input with the data after each input event. You can add a lazy attribute to change the behavior to sync after change events:

1
2
<!-- synced after "change" instead of "input" -->
<input v-model="msg" lazy>

Casting Value as Number

If you want user input to be automatically persisted as numbers, you can add a number attribute to your v-model managed inputs:

1
<input v-model="age" number>

Dynamic Select Options

When you need to dynamically render a list of options for a <select> element, it’s recommended to use an options attribute together with v-model:

1
<select v-model="selected" options="myOptions"></select>

In your data, myOptions should be an keypath/expression that points to an Array to use as its options. The Array can contain plain strings, or contain objects.

The object can be in the format of {text:'', value:''}. This allows you to have the option text displayed differently from its underlying value:

1
2
3
4
[
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' }
]

Will render:

1
2
3
4
<select>
<option value="a">A</option>
<option value="b">B</option>
</select>

Alternatively, the object can be in the format of { label:'', options:[...] }. In this case it will be rendered as an <optgroup>:

1
2
3
4
[
{ label: 'A', options: ['a', 'b']},
{ label: 'B', options: ['c', 'd']}
]

Will render:

1
2
3
4
5
6
7
8
9
10
<select>
<optgroup label="A">
<option value="a">a</option>
<option value="b">b</option>
</optgroup>
<optgroup label="B">
<option value="c">c</option>
<option value="d">d</option>
</optgroup>
</select>

Input Debounce

The debounce param allows you to set a minimum delay after each keystroke before an update is executed. This can be useful when you are performing expensive operations on each update, for example making an Ajax request for type-ahead autocompletion.

1
<input v-model="msg" debounce="500">

Result

{{msg}}

Next: Computed Properties.