When using form inputs we usually need two-way binding. In order to achieve this we can use the :value
attribute with the @input
event.
<input :value="text" @input="event => text = event.target.value" >
This can be verbose. Another way of having the same behavior is using the v-model
directive.
<!-- For input text we only use v-model --> <p>Message is: {{ message }}</p> <input v-model="message" /> <!-- Fot textarea we use it similar to input text, and not like text interpolation --> <span>Multiline message is:</span> <p style="white-space: pre-line;">{{ message }}</p> <textarea v-model="message"></textarea>
For checkboxes, when used for a single checkbox without the value
attribute, the state can take a boolean value (true
| false
). We can use the true-value
and false-value
attributes to assign the values that the state can take. These can be fixed values, or dynamic values.
For multiple related checkboxes, we assign the same model, having every element a different value for value
attribute. In this case, the state instead of holding true-false
values, store a list of values as an array, according to the checkboxes values.
const checked = ref(false) const checkedNames = reactive([]) const trueValue = ref('good') const falseValue = ref('bad')
<!-- On single checkbox the state can take boolean values: true or false --> <input type="checkbox" id="checkbox" v-model="checked" /> <label>{{ checked }}</label> <!-- Fixed values for true and false --> <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" /> <!-- Dynamic values for true and false --> <input type="checkbox" v-model="toggle" :true-value="trueValue" :false-value="falseValue" /> <div>Checked names: {{ checkedNames }}</div> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames" /><label>Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames" /><label>John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames" /><label>Mike</label>
Radio inputs work similar to checkboxes, but the only difference is that the model can take one and just one value from all related radio inputs. The values can be fixed or dynamic.
<!-- Checkbox takes only one fixed value from all radios --> <div>Picked: {{ picked }}</div> <input type="radio" id="one" value="One" v-model="picked" /><label>One</label> <input type="radio" id="two" value="Two" v-model="picked" /><label>Two</label> <!-- It can take also a dyanmic value --> <input type="radio" v-model="pick" :value="first" /> <input type="radio" v-model="pick" :value="second" />
For dropdowns, the model is set to the <select>
tag, which can take the value from any selected option. This value can be not only a fixed value, but also a dynamic one, and it can hold complex values like objects.
<div>Selected: {{ selected }}</div> <select v-model="selected"> <option disabled value="">Please select one</option> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> </select> <select v-model="selected"> <!-- inline object literal --> <option :value="{ number: 123 }">123</option> </select>
There are three modifiers that can change the behavior or apply an action over the model value. .lazy
updates the value after the change event instead the input event. .number
casts automatically the value. And .trim
removes spaces before and after the value.
<!-- Synced after "change" instead of "input" --> <input v-model.lazy="msg" /> <!-- Cast the value to number --> <input v-model.number="age" /> <!-- Trim empty characters before and after the value --> <input v-model.trim="msg" />
References