If you ever attempt to send a v-model
through a slot in Vue 3 (or Vue 2), you learn pretty quickly that it isn't possible out of the box. However, there is a workaround.
The following code example allows you to update the internal state of the SlottedComponent from a parent. This is useful in cases where you want the consumer of your component to be able to style or control its internal state.
SlottedComponent:
<template>
<slot
:input-value="inputValue"
:update-input-value="updateInputValue"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const inputValue = ref('')
const updateInputValue = (event: Event) => {
inputValue.value = (event.target as HTMLInputElement).value
}
</script>
In a parent component:
<template>
<SlottedComponent>
<template #default="{ inputValue, updateInputValue }">
<input
type="text"
:value="inputValue"
@keyup="updateInputValue"
>
</template>
</SlottedComponent>
</template>
The key here is that you cannot directly set a v-model
bound to inputValue
on the parent's input element as you typically would since it cannot cross the slot boundary. However, you can set the value
of the input to inputValue
and call an event, such as @keyup
, to send any changes back to the SlottedComponent.
I hope you found this useful. Have a great day.
Top comments (1)
Any special reason to not use
@input
? Or it's just a personal preference?