v-model on Text Inputs
Shelf's Add Book form has a title box and a notes area. As the user types, your state must hold what they typed; when you reset the form, the boxes must empty. Wiring a value binding and an input listener on every field gets old quickly. v-model does both in one attribute.
The rule
v-model is
:valuein plus@inputout: two-way, in one word.
<script setup>
import { ref } from 'vue'
const title = ref('')
const notes = ref('')
function reset() {
title.value = ''
notes.value = ''
}
</script>
<template>
<input v-model="title" placeholder="Title" />
<textarea v-model="notes"></textarea>
<p>Preview: {{ title || 'Untitled' }}</p>
<button @click="reset">Clear</button>
</template>Type "Dune" and title holds 'Dune', so the preview updates as you type. Click Clear and both boxes empty, because the state flows back into them. On a text input, v-model="title" is shorthand for:
<input :value="title" @input="title = $event.target.value" />:value="title"pushes state into the box (state → page).@input="..."copies each keystroke back into state (page → state).
Things that follow from this:
- State is the single source of truth.
v-modelignores thevalueattribute written in HTML.<input v-model="title" value="Untitled">starts empty iftitleis''. Put starting values in the ref:ref('Untitled'). - Textareas use v-model too.
<textarea>{{ notes }}</textarea>does not work for two-way binding; write<textarea v-model="notes">. - The bound thing must be writable.
v-modelneeds something it can assign to, such as a ref or an object property.v-model="title.toUpperCase()"makes no sense, since you cannot assign to a function call. Binding a prop directly is also wrong, since props are read-only; the component v-model lesson shows the right way. - Values are strings. Whatever the user types arrives as text, even in a box for page counts. The Modifiers lesson handles that.
The shortcut
When you see v-model, unfold it in your head into its two halves. Every question about it, "why is the box empty?", "why did state not change?", is answered by one half or the other.
The code
<input v-model="title" value="Untitled">withconst title = ref('').
Drills
Answer fast — trust the rule.
What does v-model="title" on a text input combine?
title is ref('') and the input has value="Untitled" plus v-model="title". What shows at first?
How do you bind a textarea two ways?
The user types 320 into a plain text input bound with v-model="pages". What type is pages?
Remember
v-model=:valueplus an input listener: state and field stay in sync both ways.- Shortcut: unfold v-model into its two halves to answer any question about it.
- Trap: HTML
value,checkedorselectedattributes are ignored; set the starting value in the ref.
