We use cookies to enhance your experience on the site
CodeWorlds

v-model on Components

v-model on native HTML elements (

<input>
,
<select>
) is a shortcut for
:value
+
@input
. But v-model also works on custom components - it's like two-way data synchronization between Earth and Mars!

How does v-model work on a component?

1<!-- Parent uses v-model -->
2<MarsInput v-model="message" />
3
4<!-- Is equivalent to: -->
5<MarsInput
6  :modelValue="message"
7  @update:modelValue="message = $event"
8/>

Implementation in the component

The component must:

  1. Accept a
    modelValue
    prop
  2. Emit an
    update:modelValue
    event
1<!-- MarsInput.vue -->
2<script setup>
3defineProps(['modelValue'])
4const emit = defineEmits(['update:modelValue'])
5</script>
6
7<template>
8  <input
9    :value="modelValue"
10    @input="emit('update:modelValue', $event.target.value)"
11  />
12</template>

Multiple v-model

Vue 3 allows multiple v-model on a single component:

1<!-- Parent -->
2<template>
3  <CrewForm
4    v-model:first-name="firstName"
5    v-model:last-name="lastName"
6  />
7</template>
8
9<!-- CrewForm.vue -->
10<script setup>
11defineProps(['firstName', 'lastName'])
12const emit = defineEmits(['update:firstName', 'update:lastName'])
13</script>
14
15<template>
16  <input
17    :value="firstName"
18    @input="emit('update:firstName', $event.target.value)"
19  />
20  <input
21    :value="lastName"
22    @input="emit('update:lastName', $event.target.value)"
23  />
24</template>

v-model Modifiers

You can create custom modifiers:

1<!-- Parent -->
2<MarsInput v-model.uppercase="text" />
3
4<!-- MarsInput.vue -->
5<script setup>
6const props = defineProps({
7  modelValue: String,
8  modelModifiers: { default: () => ({}) }
9})
10const emit = defineEmits(['update:modelValue'])
11
12function onInput(e) {
13  let value = e.target.value
14  if (props.modelModifiers.uppercase) {
15    value = value.toUpperCase()
16  }
17  emit('update:modelValue', value)
18}
19</script>
20
21<template>
22  <input :value="modelValue" @input="onInput" />
23</template>
Go to CodeWorlds