Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Forms Handling  ›  Lesson

v-model on Text Inputs

Input Bindings 12 minv-model keeps an input and a piece of state in sync in both directions, as shorthand for a value binding plus an input listener.

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 :value in plus @input out: 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-model ignores the value attribute written in HTML. <input v-model="title" value="Untitled"> starts empty if title is ''. 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-model needs 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.

Why does the title box start empty?Step 1 of 4
  1. The code

    <input v-model="title" value="Untitled"> with const title = ref('').

Drills

Answer fast — trust the rule.

quick drill

What does v-model="title" on a text input combine?

quick drill

title is ref('') and the input has value="Untitled" plus v-model="title". What shows at first?

quick drill

How do you bind a textarea two ways?

quick drill

The user types 320 into a plain text input bound with v-model="pages". What type is pages?

Remember

  • v-model = :value plus 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, checked or selected attributes are ignored; set the starting value in the ref.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainUnpack v-model

Rewrite <input v-model="title" /> without v-model, then explain what each half does and why value="Untitled" written on the same input would be ignored.