How to use v-model in Vue 3?
In Vue 3, the v-model has been completely changed and is no longer compatible with the Vue 2 syntax. In this article, I will explain how to use the v-model in Vue 3, and what new functionality it brings. Before I do that, let's quickly look at the old syntax.
Old v-model syntax in Vue 2
Let's say we have a Parent component that contains a custom TextField component:
// ParentComponent.vue
<template>
<TextField v-model="providedUsername" />
</template>
<script>
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
data: function() {
return {
providedUsername: null,
};
},
};
</script>The TextField component is compatible with v-model because it uses the value property and emits the input event:
// TextField.vue
<template>
<input type="text" :value="value" @input="$emit('input', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
value: String
}
};
</script>New v-model in Vue 3
Now, let's see how to use the v-model in Vue 3. Let's start with the parent component. The main change in Vue 3 is that instead of the data function, we use the setup() to define a reference to the username field:
// ParentComponent.vue
<template>
<TextField v-model="providedUsername" />
</template>
<script>
import { ref } from "vue";
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
setup() {
const providedUsername = ref(null);
return { providedUsername };
}
};
</script>Now, let's define the TextField component:
// TextField.vue
<template>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
modelValue: {
type: String
}
}
};
</script>The big change is that for the v-model we no longer use the value property. Instead, in Vue 3, we use the modelValue. A similar situation is with the event. Instead of the input event, we emit the update:modelValue.
In summary, to migrate v-model from Vue 2 to Vue 3 rename :
- prop:
value->modelValue - event:
input->update:modelValue
Custom v-model argument
Vue 3 allows to easily use a custom property name with v-model. Let's say we want to use a username property. In that case, the parent component will look like this:
// ParentComponent.vue
<template>
<TextField v-model:username="providedUsername" />
</template>
<script>
import { ref } from "vue";
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
setup() {
const providedUsername = ref(null);
return { providedUsername };
}
};
</script>To make the TextField work with the v-model, all we have to do is update the property and event by replacing the modelValue with username:
// TextField.vue
<template>
<input type="text" :value="username" @input="$emit('update:username', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
username: {
type: String
}
}
};
</script>Multiple v-models in one component
Another new feature of Vue 3 is the ability to use multiple v-models in one component:
// ParentComponent.vue
<template>
<LoginForm v-model:username="providedUsername" v-model:password="providedPassword" />
</template>
<script>
import { ref } from "vue";
import LoginForm from "./LoginForm";
export default {
name: "ParentComponent",
components: {
LoginForm
},
setup() {
const providedUsername = ref(null);
const providedPassword = ref(null);
return { providedUsername, providedPassword };
}
}
</script>// LoginForm.vue
<template>
<form>
<input type="text" :value="username" @input="$emit('update:username', $event.target.value)" />
<input type="password" :value="password" @input="$emit('update:password', $event.target.value)" />
</form>
</template>
<script>
export default {
name: "TextField",
props: {
username: {
type: String
},
password: {
type: String
}
}
};
</script>That's it. I hope this article was helpful and now you know how to use the v-model in Vue 3.