v-model — Two-Way Binding

Form Inputs Sync to Refs Automatically

v-model — Two-Way Binding

v-model is shorthand for :value plus @input. It works on inputs, selects, checkboxes, textareas, and custom components.

4 min read Level 2/5 #vue#directives#forms
What you'll learn
  • Bind a text input with v-model
  • Bind a checkbox / select
  • Use v-model on a custom component

v-model wires a form input directly to a ref. It saves you from writing a value bind and an event listener for every field.

Text Inputs

<script setup lang="ts">
import { ref } from 'vue'
const name = ref('')
</script>

<template>
  <input v-model="name" placeholder="Your name" />
  <p>Hello {{ name }}</p>
</template>

That is exactly equivalent to writing it the long way:

<input
  :value="name"
  @input="name = ($event.target as HTMLInputElement).value"
/>

Checkboxes, Selects, Radios

v-model adapts to the input type. A single checkbox is a boolean; multiple checkboxes share an array.

<script setup lang="ts">
import { ref } from 'vue'
const agree = ref(false)
const toppings = ref<string[]>([])
const color = ref('red')
</script>

<template>
  <input type="checkbox" v-model="agree" />

  <input type="checkbox" value="cheese" v-model="toppings" />
  <input type="checkbox" value="olives" v-model="toppings" />

  <select v-model="color">
    <option>red</option>
    <option>blue</option>
  </select>
</template>

Custom Components

To make your own component v-model-able, call defineModel inside <script setup>:

<script setup lang="ts">
const model = defineModel<string>()
</script>

<template>
  <input :value="model" @input="model = ($event.target as HTMLInputElement).value" />
</template>

Then a parent uses it like any input: <MyInput v-model="name" />.

v-on (Events) & Modifiers →