LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1116 min read

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>
What It Expands To

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

ModifierBehavior
.lazySyncs on the change event instead of input — updates after the field loses focus, not on every keystroke
.numberAutomatically casts the input's string value to a number
.trimAutomatically trims whitespace from the input's value
<input v-model.number="age" type="number" />
<input v-model.trim="username" />

Common Beginner Mistakes

Forgetting that inputs are strings by default

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.

Mixing v-model and :value on the same input

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.

Next Lesson →

Computed Properties