Skip to main content
Practice Problems

V-model in Vue.js

What is v-model?

v-model is a Vue directive that creates two-way data binding between form elements and component data.

javascript
<template> <input v-model="message" /> <p>Message: {{ message }}</p> </template> <script setup> import { ref } from 'vue' const message = ref('Hello') </script>

When user types text, message updates automatically, and vice versa.


How v-model Works

v-model is syntactic sugar over value binding and event handling:

javascript
<!-- With v-model --> <input v-model="text" /> <!-- Equivalent to --> <input :value="text" @input="text = $event.target.value" />

Vue automatically:

  1. Binds value to data (:value)
  2. Listens for change event (@input)
  3. Updates data on change

v-model with Different Elements

Input (text)

javascript
<template> <input v-model="text" type="text" /> </template> <script setup> import { ref } from 'vue' const text = ref('') </script>

Textarea

javascript
<template> <textarea v-model="message"></textarea> <p>{{ message }}</p> </template> <script setup> import { ref } from 'vue' const message = ref('Multi-line text') </script>

Checkbox (single)

javascript
<template> <input type="checkbox" v-model="checked" /> <span>Agreed: {{ checked }}</span> </template> <script setup> import { ref } from 'vue' const checked = ref(false) </script>

Checkbox (multiple)

javascript
<template> <input type="checkbox" value="Vue" v-model="frameworks" /> <input type="checkbox" value="React" v-model="frameworks" /> <input type="checkbox" value="Angular" v-model="frameworks" /> <p>Selected: {{ frameworks }}</p> </template> <script setup> import { ref } from 'vue' const frameworks = ref([]) </script>

Radio

javascript
<template> <input type="radio" value="male" v-model="gender" /> <input type="radio" value="female" v-model="gender" /> <p>Gender: {{ gender }}</p> </template> <script setup> import { ref } from 'vue' const gender = ref('male') </script>

Select

javascript
<template> <select v-model="selected"> <option disabled value="">Choose</option> <option value="A">Option A</option> <option value="B">Option B</option> <option value="C">Option C</option> </select> <p>Selected: {{ selected }}</p> </template> <script setup> import { ref } from 'vue' const selected = ref('') </script>

v-model Modifiers

.lazy

By default, v-model updates on input event. The .lazy modifier switches to change:

javascript
<template> <!-- Updates only after blur --> <input v-model.lazy="message" /> </template>

.number

Automatically converts value to number:

javascript
<template> <input v-model.number="age" type="number" /> </template> <script setup> import { ref } from 'vue' const age = ref(0) // age is always a number, not a string </script>

.trim

Automatically trims whitespace:

javascript
<template> <input v-model.trim="username" /> </template> <script setup> import { ref } from 'vue' const username = ref('') </script>

Combining Modifiers

javascript
<template> <input v-model.lazy.trim="message" /> <input v-model.number.lazy="age" type="number" /> </template>

v-model in Custom Components

Composition API

In Composition API, v-model works with modelValue prop and update:modelValue event:

javascript
<!-- ParentComponent.vue --> <template> <CustomInput v-model="searchText" /> </template> <script setup> import { ref } from 'vue' import CustomInput from './CustomInput.vue' const searchText = ref('') </script>
javascript
<!-- CustomInput.vue --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script setup> defineProps(['modelValue']) defineEmits(['update:modelValue']) </script>

Using Computed for Simplification

javascript
<!-- CustomInput.vue --> <template> <input v-model="value" /> </template> <script setup> import { computed } from 'vue' const props = defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) const value = computed({ get() { return props.modelValue }, set(value) { emit('update:modelValue', value) } }) </script>

Multiple v-model (Vue 3)

In Vue 3, you can use multiple v-model on one component:

javascript
<!-- UserForm.vue --> <template> <UserName v-model:first-name="firstName" v-model:last-name="lastName" /> </template> <script setup> import { ref } from 'vue' const firstName = ref('') const lastName = ref('') </script>
javascript
<!-- UserName.vue --> <template> <input :value="firstName" @input="$emit('update:firstName', $event.target.value)" placeholder="First Name" /> <input :value="lastName" @input="$emit('update:lastName', $event.target.value)" placeholder="Last Name" /> </template> <script setup> defineProps(['firstName', 'lastName']) defineEmits(['update:firstName', 'update:lastName']) </script>

Custom Modifiers

You can create custom modifiers:

javascript
<!-- Parent.vue --> <template> <MyComponent v-model.capitalize="myText" /> </template>
javascript
<!-- MyComponent.vue --> <template> <input :value="modelValue" @input="handleInput" /> </template> <script setup> const props = defineProps({ modelValue: String, modelModifiers: { default: () => ({}) } }) const emit = defineEmits(['update:modelValue']) function handleInput(event) { let value = event.target.value if (props.modelModifiers.capitalize) { value = value.charAt(0).toUpperCase() + value.slice(1) } emit('update:modelValue', value) } </script>

Common Mistakes

Mutating props directly

javascript
<!-- Wrong --> <template> <input v-model="modelValue" /> </template> <script setup> defineProps(['modelValue']) // Vue will warn about mutating props </script> <!-- Correct --> <template> <input v-model="value" /> </template> <script setup> import { computed } from 'vue' const props = defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) const value = computed({ get: () => props.modelValue, set: (val) => emit('update:modelValue', val) }) </script>

Conclusion

v-model:

  • Creates two-way data binding
  • Syntactic sugar over :value and @input
  • Works with different form elements
  • Has modifiers: .lazy, .number, .trim
  • In Vue 3 supports multiple usage
  • Can be used in custom components

In interviews:

Important to be able to:

  • Explain what v-model is and how it works
  • Show how v-model expands to :value + @input
  • Describe modifiers
  • Explain how to use v-model in custom components
  • Give examples with different form elements

Content

What is v-model?How v-model Worksv-model with Different ElementsInput (text)TextareaCheckbox (single)Checkbox (multiple)RadioSelectv-model Modifiers.lazy.number.trimCombining Modifiersv-model in Custom ComponentsComposition APIUsing Computed for SimplificationMultiple v-model (Vue 3)Custom ModifiersCommon MistakesMutating props directlyConclusion

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems