--- name: component-v-model description: Implement two-way data binding on custom components --- # Component v-model Create two-way bindings between parent and child components. ## defineModel() (3.4+, Recommended) The simplest way to implement v-model: ```vue ``` ```vue-html ``` `defineModel()` returns a ref that: - Syncs with parent's bound value - Emits `update:modelValue` when mutated ### With Options ```ts // Required model const model = defineModel({ required: true }) // With default const model = defineModel({ default: 0 }) ``` ## Named v-model Use arguments for multiple v-models: ```vue ``` ```vue-html ``` ## v-model Modifiers Access and handle modifiers: ```vue-html ``` ```vue ``` ### Transform with Modifiers Use `get` and `set` options: ```vue ``` ### Modifiers with Named v-model ```vue-html ``` ```ts const [title, titleModifiers] = defineModel('title') console.log(titleModifiers) // { capitalize: true } ``` ## Manual Implementation (Pre-3.4) Understanding what `defineModel` does under the hood: ```vue ``` For named v-model `v-model:title`: ```ts defineProps<{ title: string }>() defineEmits<{ 'update:title': [value: string] }>() ``` ## Typing defineModel ```ts // Basic const model = defineModel() // ^? Ref // Required (removes undefined) const model = defineModel({ required: true }) // ^? Ref // With modifiers const [model, modifiers] = defineModel() // ^? Record<'trim' | 'capitalize', true | undefined> ``` ## Warning: Default Values Having a default in `defineModel` without providing a value from parent causes desync: ```vue ```