Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Vue Forms — v-model

v-model — Two-Way Binding

v-model creates a two-way binding between a form input and reactive data. It's shorthand for :value="data" + @input="data = $event.target.value". Vue's v-model is much simpler than React's controlled components.

v-model — All Input Types and Validation
<template>
  <form @submit.prevent="handleSubmit">
    <!-- Text input -->
    <input v-model="form.name" placeholder="Name" />

    <!-- Email -->
    <input v-model="form.email" type="email" placeholder="Email" />

    <!-- Number with .number modifier -->
    <input v-model.number="form.age" type="number" />

    <!-- Textarea -->
    <textarea v-model="form.bio" rows="4" />

    <!-- Select -->
    <select v-model="form.country">
      <option value="">Select country</option>
      <option value="us">United States</option>
      <option value="uk">United Kingdom</option>
      <option value="in">India</option>
    </select>

    <!-- Multi-select -->
    <select v-model="form.skills" multiple>
      <option v-for="skill in availableSkills" :key="skill" :value="skill">
        {{ skill }}
      </option>
    </select>

    <!-- Radio buttons -->
    <label v-for="role in roles" :key="role">
      <input type="radio" v-model="form.role" :value="role" />
      {{ role }}
    </label>

    <!-- Checkbox (boolean) -->
    <label>
      <input type="checkbox" v-model="form.newsletter" />
      Subscribe to newsletter
    </label>

    <!-- Checkbox (array) -->
    <label v-for="tag in availableTags" :key="tag">
      <input type="checkbox" v-model="form.tags" :value="tag" />
      {{ tag }}
    </label>

    <button type="submit">Submit</button>
    <pre>{{ JSON.stringify(form, null, 2) }}</pre>
  </form>
</template>

<script setup>
import { reactive } from 'vue'

const form = reactive({
  name: '', email: '', age: 0, bio: '',
  country: '', skills: [], role: 'user',
  newsletter: false, tags: []
})

const availableSkills = ['Vue', 'React', 'Angular', 'Node.js']
const roles = ['user', 'admin', 'moderator']
const availableTags = ['Frontend', 'Backend', 'DevOps', 'Design']

function handleSubmit() {
  console.log('Form submitted:', form)
}
</script>
<template>
  <form @submit.prevent="handleSubmit">
    <div class="field">
      <input v-model="form.email" type="email" placeholder="Email"
        :class="{ 'input-error': errors.email }" @blur="validateField('email')" />
      <span v-if="errors.email" class="error">{{ errors.email }}</span>
    </div>

    <div class="field">
      <input v-model="form.password" type="password" placeholder="Password"
        :class="{ 'input-error': errors.password }" @blur="validateField('password')" />
      <span v-if="errors.password" class="error">{{ errors.password }}</span>
    </div>

    <button type="submit" :disabled="!isValid">Login</button>
  </form>
</template>

<script setup>
import { reactive, computed } from 'vue'

const form = reactive({ email: '', password: '' })
const errors = reactive({ email: '', password: '' })

function validateField(field) {
  if (field === 'email') {
    if (!form.email) errors.email = 'Email is required'
    else if (!/\S+@\S+\.\S+/.test(form.email)) errors.email = 'Invalid email'
    else errors.email = ''
  }
  if (field === 'password') {
    if (!form.password) errors.password = 'Password is required'
    else if (form.password.length < 8) errors.password = 'Min 8 characters'
    else errors.password = ''
  }
}

const isValid = computed(() =>
  form.email && form.password && !errors.email && !errors.password
)

function handleSubmit() {
  validateField('email')
  validateField('password')
  if (isValid.value) alert('Login successful!')
}
</script>

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.