Vue 3.4 defineModel — game changing feature!

Mustafa Çağrı Güven
3 min readJan 20, 2024

--

Hey Vue enthusiasts! Vue 3 stepped onto the scene on September 18, 2020, but let’s face it — getting it into production had its challenges. Popular packages like Vuetify took their time catching up, and developers were a bit hesitant, feeling somewhat like the transition from Angular 1 to Angular 2.

Vue 3.4 defineModel — Vue 3: two way binding with defineModel!

Until Vue 3.3 (May 2023), Vue 3 wasn’t stealing the spotlight, but post that version, it’s been making a comeback, just like the good old days. (Between you and me, I’ve dabbled in both Vue and React, explored React for some syntax sugar, but, shh, Vue remains my preferred choice these days.)

Now, fast forward, Vue 3 has matured, dishing out some nifty syntactic sugar. While I was initially hooked on <script setup>, today, let’s dive into another gem — defineModel. Before Vue 3.4, we were juggling props, modelValue, and emitting events. But hooray! Achieving smooth two-way binding between parent and child components is now a piece of cake.

Super easy, right? How was that before?

For me, the first one is crystal clear, seriously boosting readability. Vue keeps getting better, and I’m loving the journey!

v-model modifiers

From the original documentation, we can also use the modifiers with this new game changing feature.

When we were learning about form input bindings, we saw that v-model has built-in modifiers - .trim, .number and .lazy. In some cases, you might also want the v-model on your custom input component to support custom modifiers.

Let’s create an example custom modifier, capitalize, that capitalizes the first letter of the string provided by the v-model binding:

<MyComponent v-model.capitalize="myText" />

Modifiers added to a component v-model can be accessed in the child component by destructuring the defineModel() return value like this:

<script setup>
const [model, modifiers] = defineModel()
console.log(modifiers) // { capitalize: true }
</script>
<template>
<input type="text" v-model="model" />
</template>

To conditionally adjust how the value should be read / written based on modifiers, we can pass get and set options to defineModel(). These two options receive the value on get / set of the model ref and should return a transformed value. This is how we can use the set option to implement the capitalize modifier:

<script setup>
const [model, modifiers] = defineModel({
set(value) {
if (modifiers.capitalize) {
return value.charAt(0).toUpperCase() + value.slice(1)
}
return value
}
})
</script>

<template>
<input type="text" v-model="model" />
</template>

How we were handling this before Vue 3.4

<script setup>
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => ({}) }
})
const emit = defineEmits(['update:modelValue'])
function emitValue(e) {
let value = e.target.value
if (props.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
emit('update:modelValue', value)
}
</script>
<template>
<input type="text" :value="modelValue" @input="emitValue" />
</template>

For the more details:

Stay tuned for more exciting Vue 3 featuresKeep rocking with Vue 3! 🚀

--

--

Mustafa Çağrı Güven
Mustafa Çağrı Güven

Written by Mustafa Çağrı Güven

Comp. Eng. @Sabancı University Graduated '11 / Senior Frontend Wizard / Vue.js 3 / Node.js / Express.js / MEVN / Nuxt 3 / Clean Code & Open Source ❤

Responses (1)