Forms & v-model
Build two-way bound form inputs using the v-model directive across text fields, checkboxes, and selects.
What v-model Does
v-model creates two-way binding on a form input: it sets the input's value from a reactive variable, and updates that variable whenever the user types or changes the input — without you writing separate v-bind and @input handlers yourself.
<script setup>import { ref } from 'vue';const name = ref('');</script>
<template> <input v-model="name" placeholder="Your name" /> <p>Hello, {{ name }}!</p></template>v-model="name" is shorthand for :value="name" combined with @input="name = $event.target.value" — understanding this makes it easier to reason about what v-model is actually doing under the hood.
Text Inputs and Textareas
<input v-model="message" type="text" /><textarea v-model="description"></textarea>Checkboxes
A single checkbox binds to a boolean. Multiple checkboxes sharing the same v-model bind to an array, automatically pushing or removing values as they're checked.
<script setup>import { ref } from 'vue';const subscribed = ref(false);const interests = ref([]);</script>
<template> <input type="checkbox" v-model="subscribed" /> Subscribe
<input type="checkbox" value="sports" v-model="interests" /> Sports <input type="checkbox" value="music" v-model="interests" /> Music</template>Radio Buttons and Select
<script setup>import { ref } from 'vue';const plan = ref('basic');</script>
<template> <input type="radio" value="basic" v-model="plan" /> Basic <input type="radio" value="pro" v-model="plan" /> Pro
<select v-model="plan"> <option value="basic">Basic</option> <option value="pro">Pro</option> </select></template>v-model Modifiers
| Modifier | Behavior |
|---|---|
| .lazy | Syncs on the change event instead of input — updates after the field loses focus, not on every keystroke |
| .number | Automatically casts the input's string value to a number |
| .trim | Automatically trims whitespace from the input's value |
<input v-model.number="age" type="number" /><input v-model.trim="username" />Common Beginner Mistakes
Without .number, v-model always gives you a string, even for a type="number" input — remember to convert or use the modifier when you need an actual number.
v-model already includes value binding — combining both leads to conflicting, confusing behavior.
FAQs
Yes — a component can accept v-model by defining a modelValue prop and emitting an update:modelValue event, covered in the custom events lesson.
It only makes sense for numeric input — for anything else, leave that modifier off and validate/convert the string as needed in your own logic.
Summary
v-model gives you two-way binding across every common form input type, with modifiers covering the most frequent needs. Next, you'll learn computed properties for deriving values from reactive state.