Vue v-model
Directive
Compared to normal JavaScript, it is easier to work with forms in Vue because the v-model
directive connects with all types of input elements in the same way.
v-model
creates a link between the input element value
attribute and a data value in the Vue instance. When you change the input, the data updates and when the data changes, the input updates as well (two-way binding).
Two-way Binding
As we have already seen in the shopping list example on the previous page, v-model
provides us with a two-way binding, meaning that the form input elements update the Vue data instance, and a change in the Vue instance data updates the inputs.
The example below also demonstrates the two-way binding with v-model
.
Example
Two-way binding: Try to write inside the input field to see that the Vue data property value gets updated. Try also to write directly in the code to change the Vue data property value, run the code, and see how the input field is updated.
<div id="app">
<input type="text" v-model="inpText">
<p> {{ inpText }} </p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
inpText: 'Initial text'
}
}
})
app.mount('#app')
</script>
Try it Yourself »
Note: The v-model
two-way binding functionality could actually be achieved with a combination of v-bind:value
and v-on:input
:
v-bind:value
to update the input element from the Vue instance data,- and
v-on:input
to update the Vue instance data from the input.
But v-model
is much easier to use so that is what we will do.
A Dynamic Checkbox
We add a checkbox to our shopping list on the previous page to mark if an item is important or not.
Next to the checkbox we add a text that allways reflects the current 'important' status, changing dynamically between 'true' or 'false'.
We use v-model
to add this dynamic checkbox and text to improve user interaction.
We need:
- a boolean value in the Vue instance data property called 'important'
- a checkbox where the user can check if the item is important
- a dynamic feedback text so that the user can see if the item is important
Below is how the 'important' feature looks, isolated from the shopping list.
Example
The checkbox text is made dynamic so that the text reflects the current checkbox input value.
<div id="app">
<form>
<p>
Important item?
<label>
<input type="checkbox" v-model="important">
{{ important }}
</label>
</p>
</form>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
important: false
}
}
})
app.mount('#app')
</script>
Try it Yourself »
Let's include this dynamic feature in our shopping list example.
Example
<div id="app">
<form v-on:submit.prevent="addItem">
<p>Add item</p>
<p>Item name: <input type="text" required v-model="itemName"></p>
<p>How many: <input type="number" v-model="itemNumber"></p>
<p>
Important?
<label>
<input type="checkbox" v-model="itemImportant">
{{ important }}
</label>
</p>
<button type="submit">Add item</button>
</form>
<hr>
<p>Shopping list:</p>
<ul>
<li v-for="item in shoppingList">{{item.name}}, {{item.number}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
itemName: null,
itemNumber: null,
important: false,
shoppingList: [
{ name: 'Tomatoes', number: 5, important: false }
]
}
},
methods: {
addItem() {
let item = {
name: this.itemName,
number: this.itemNumber
important: this.itemImportant
}
this.shoppingList.push(item)
this.itemName = null
this.itemNumber = null
this.itemImportant = false
}
}
})
app.mount('#app')
</script>
Try it Yourself »
Mark Found Items in The Shopping List
Let's add functionality so that items added to the shopping list can be marked as found.
We need:
- the list items to react on click
- to change the status of the clicked item to 'found', and use this to visually move the item away and strike it through with CSS
We create one list with all items we need to find, and one list below with items found striked through. We can actually put all the items in the first list, and all the items in the second list, and just use v-show
with the Vue data property 'found' to define whether to show the item in the first or second list.
Example
After adding items to the shopping list we can pretend to go shopping, clicking the items away after finding them. If we click an item by mistake we can take it back to the 'not found' list by clicking the item once more.
<div id="app">
<form v-on:submit.prevent="addItem">
<p>Add item</p>
<p>Item name: <input type="text" required v-model="itemName"></p>
<p>How many: <input type="number" v-model="itemNumber"></p>
<p>
Important?
<label>
<input type="checkbox" v-model="itemImportant">
{{ important }}
</label>
</p>
<button type="submit">Add item</button>
</form>
<p><strong>Shopping list:</strong></p>
<ul id="ulToFind">
<li v-for="item in shoppingList"
v-bind:class="{ impClass: item.important }"
v-on:click="item.found=!item.found"
v-show="!item.found">
{{ item.name }}, {{ item.number}}
</li>
</ul>
<ul id="ulFound">
<li v-for="item in shoppingList"
v-bind:class="{ impClass: item.important }"
v-on:click="item.found=!item.found"
v-show="item.found">
{{ item.name }}, {{ item.number}}
</li>
</ul>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
itemName: null,
itemNumber: null,
important: false,
shoppingList: [
{ name: 'Tomatoes', number: 5, important: false, found: false }
]
}
},
methods: {
addItem() {
let item = {
name: this.itemName,
number: this.itemNumber,
important: this.itemImportant,
found: false
}
this.shoppingList.push(item)
this.itemName = null
this.itemNumber = null
this.itemImportant = false
}
}
})
app.mount('#app')
</script>
Try it Yourself »
Use v-model to make The Form Itself Dynamic
We can make a form where the customer orders from a menu. To make it easy for the customer, we only present the drinks to choose from after the customer chooses to order drinks. This is can be argued to be better than presenting the customer with all items from the menu at once. In this example we use v-model
and v-show
to make the form itself dynamic.
We need:
- A form, with relevant input tags and 'Order' button.
- Radio-buttons to select 'Dinner', 'Drink' or 'Dessert'.
- After category is chosen, a dropdown menu appears with all the items in that category.
- When an item is chosen you see an image of it, you can choose how many and add it to the order. The form is reset when the item is added to the order.
Example
This form is dynamic. It changes based on user choices. The user must first choose category, then product and how many, before the order button becomes visible and the user can order it.
Try it Yourself »