Using v-model with objects in Vue3
Blind Kai
Posted on November 30, 2021
Motivation
When I was using Vue2 along with vue-class-component
and vue-property-decorator
it was easy to synchronize v-models
between components simply using @ModelSync()
. When Vue 3 came out with its Composition API another way was needed to achieve the same result as if Class Component was used.
Implementation
If you're already familiar with the capabilities of Composition API, then simply use computed
within setup
to update the modelValue
whenever it changes.
1) In child component define a model property with the default value
import { defineComponent } from 'vue';
<script>
export default defineComponent({
name: 'FancyComponent',
props: {
modelValue: { // Declare the property
type: Object,
default: () => ({}), // Do not forget about default value
},
}
});
</script>
2) In setup()
define a computed property and expose it:
<template>
<div>
<input v-model="theModel.foo" /> <!-- Usage of model -->
</div>
</template>
<script>
import { defineComponent, computed } from 'vue';
export default defineComponent({
name: 'FancyComponent',
emits: ['update:modelValue'], // The component emits an event
props: {
modelValue: {
type: Object,
default: () => ({}),
},
},
setup(props, { emit }) {
const theModel = computed({ // Use computed to wrap the object
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value),
});
return { theModel };
}
});
</script>
3) In parent component use v-model
directive:
<template>
<FancyComponent v-model="someObject" />
</template>
TypeScript
In the case of using TypeScript, there is one minor addition to the code above. PropType<T>
is used it order to annotate the model type.
<script>
import { defineComponent, computed, PropType } from 'vue';
interface OurModelType {
foo: string;
}
export default defineComponent({
name: 'FancyComponent',
emits: ['update:modelValue'],
props: {
modelValue: {
type: Object as PropType<OurModelType>, // Type Annotation
default: () => ({}),
},
},
setup(props, { emit }) {
const theModel = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value),
});
return { theModel };
}
});
</script>
And it's all you need to know to pass reactive objects into your custom components as v-model
.
Posted on November 30, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024
November 30, 2024