Skip to content
Advertisement

Pass events easily from a child component to a parent in Vue 2

I have a base component BaseInput.vue which accepts attributes and emits events. It’s easy to bind all attributes by using v-bind="$attrs" instruction.

// BaseInput.vue
<template>
  <label>
    <input
      v-bind="$attrs"
      @focus="$emit('focus')"
      @blur="$emit('blur')"
    >
  </label>
</template>

<script>
export default {
  inheritAttrs: false,
};
</script>

Next I have a wrapper component WrapInput.vue which passes attributes to BasicInput and emits events.

// WrapInput.vue
<template>
  <basic-input
    v-bind="$attrs"
    @focus="$emit('focus')"
    @blur="$emit('blur')"
  />
</template>

<script>
import BasicInput from '@/storybook/pages/BasicInput';

export default {
  components: { BasicInput },
  inheritAttrs: false,
};
</script>

My question: is there a handy way in Vue to pass a bunch of events in “proxy” components without the need to list them one by one? I expect something like this:

// WrapInput.vue
<template>
  <basic-input
    v-bind="$attrs"
    v-bind="$events" // is it possible to proxy all events in a single line?
  />
</template>

<script>
import BasicInput from '@/storybook/pages/BasicInput';

export default {
  components: { BasicInput },
  inheritAttrs: false,
};
</script>

P.S. I’ve heard about EventBus, but doesn’t fit nicely for my case.

Advertisement

Answer

In Vue 2, you could use v-on and $listeners to pass any event listeners to a component:

// BasicInput.vue
<input v-on="$listeners">

Vue 2 demo

In Vue 3, $listeners is removed, but any event listeners would be part of $attrs, so v-bind="$attrs" would suffice.

Vue 3 demo

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement