How-To

How-To · Reactivity

How to Handle Form Input in Vue with v-model

Capture what a user types in three steps: hold the value in a ref, bind the input with v-model, and read it back — with a live demo that echoes the typed text.

XCODXHow-To · Updated

Overview

Handling text input in Vue comes down to connecting a form field to a piece of reactive state so the two always agree. You store the value in a ref, bind the field to it with v-model, and from then on the ref holds whatever the user typed — ready to read, validate, or send. This is the standard, recommended approach and it takes only a few lines.

Steps

1. Hold the value in a ref

Start with the state. Create a ref to hold the field's value, initialised to an empty string for a text input. This ref is the single source of truth for what is in the field — everything else in these steps just keeps it and the input synchronised.

<script setup>
import { ref } from 'vue';

const text = ref('');
</script>

2. Bind the input with v-model

Add v-model="text" to the input element. This sets up a two-way binding: the field displays the ref's current value, and every keystroke writes the new value straight back into the ref. There is no event handler to wire up by hand — v-model does both directions for you.

<template>
  <input v-model="text" />
</template>

3. Read the value

The ref now holds the live value, so you can use it anywhere. In the template read it by bare name — {{ text }} — and it updates as the user types; in script read text.value to validate it or send it to an API. Because it is reactive, anything derived from it stays in sync automatically.

<template>
  <input v-model="text" />
  <p>You typed: {{ text }}</p>
</template>

4. Understand what v-model expands to

It helps to know that v-model is not magic — on a text input it is shorthand for binding :value and listening to @input. Writing the two out by hand produces exactly the same result, which is worth seeing once so the binding never feels opaque.

<!-- these two inputs behave identically -->
<input v-model="text" />

<input :value="text" @input="text = $event.target.value" />

Runnable example

The complete, running version — type in the field and the text echoes below it live, straight from the ref:

Common pitfalls

If you need to transform input as it is typed — force uppercase, strip spaces — reach for the expanded :value + @input form from step 4, or add a v-model modifier such as .trim. That gives you a hook to adjust the value on its way into the ref, which the plain binding does not expose.

Frequently asked questions

How do I get the value of an input in Vue?
Create a ref, bind the input with v-model="yourRef", and the ref holds whatever the user types. Read it by bare name in the template or through .value in script.
What is v-model shorthand for on a text input?
On a text input, v-model="text" is shorthand for :value="text" combined with @input="text = $event.target.value". It binds the value one way and updates the ref on input the other way.
Do I use .value with v-model?
No. Bind to the ref itself — v-model="text" — because the template auto-unwraps the ref. Writing v-model="text.value" breaks the binding. You only use .value when reading the ref in script.