DEV Community

Jason Shimkoski
Jason Shimkoski

Posted on • Edited on

Sending a V-Model Through a Slot in Vue 3

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>
Enter fullscreen mode Exit fullscreen mode

In a parent component:

<template>
  <SlottedComponent>
    <template #default="{ inputValue, updateInputValue }">
      <input
        type="text"
        :value="inputValue"
        @keyup="updateInputValue"
      >
    </template>
  </SlottedComponent>
</template>
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
robsonsobral profile image
Robson Sobral

Any special reason to not use @input? Or it's just a personal preference?