Roadmap › Vue.js 3 (with Pinia, Vue Router & Nuxt basics) › Module: Router, State and Forms
Lessons in this course (17)

14. Forms and validation

IntermediateMediumLesson 14 of 17
vue
<script setup lang="ts">
import { reactive, computed } from "vue";
const form = reactive({ email: "", qty: 1, agree: false, size: "M", tags: [] as string[] });
const emailError = computed(() => form.email && !/^\S+@\S+\.\S+$/.test(form.email) ? "Invalid email" : "");
const canSubmit = computed(() => !emailError.value && form.email && form.agree);
</script>
<template>
  <form @submit.prevent="canSubmit && save(form)">
    <input v-model.trim="form.email" type="email" />
    <small v-if="emailError">{{ emailError }}</small>
    <input v-model.number="form.qty" type="number" min="1" />
    <input v-model="form.agree" type="checkbox" />
    <select v-model="form.size"><option>S</option><option>M</option><option>L</option></select>
    <label><input v-model="form.tags" type="checkbox" value="gift" /> Gift</label>
    <button :disabled="!canSubmit">Save</button>
  </form>
</template>

For larger forms: VeeValidate (+ Zod/Yup schemas) or FormKit.