vue icon indicating copy to clipboard operation
vue copied to clipboard

Modifier to propagate/forward events to parent

Open Vontus opened this issue 5 years ago • 18 comments

What problem does this feature solve?

Currently, and as far as I know, if we want to propagate an event fired by a child component to the parent (the child's grandparent) we need to $emit the event again, and we need to pass all the arguments one more time. This can become a problem, for example, if the event has a variable number of arguments because we need to specify them manually or pass the whole array as a new argument.

The current way would be something like

@blur="$emit('blur')"
@create="$emit('create', arguments[0])"
@input="$emit('input', arguments[0], arguments[1])"

What does the proposed API look like?

@blur.propagate
@create.propagate
@input.propagate

And if we want to both handle the event and propagate it to the parent, we would use

@input.propagate="someFunction"

EDIT: Maybe since .propagate may be confused with the function .stopPropagation(), a better term could be simply .emit

Vontus avatar Jan 15 '19 11:01 Vontus

why not just @input="$emit('input', arguments)" ?

I do like having a dedicated keyword though

lopugit avatar Jan 16 '19 05:01 lopugit

@lopugit because passing the whole array in one argument would make users handle the same event differently in different components, plus it is a little redundant.

Vontus avatar Jan 16 '19 07:01 Vontus

Isn't propagating arguments upwards what you want??

On Wed., 16 Jan. 2019, 6:50 pm Vontus <[email protected] wrote:

@lopugit https://github.com/lopugit because passing the whole array in one argument would make users handle the same event differently in different components, plus it is a little redundant.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vuejs/vue/issues/9325#issuecomment-454683246, or mute the thread https://github.com/notifications/unsubscribe-auth/AM_3BshACHBnU8nluMZLTLrOAGxiD6NEks5vDtmzgaJpZM4aAyIG .

lopugit avatar Jan 16 '19 09:01 lopugit

You should be able to use the spread operator, ala:

@input="$emit('input', ...arguments)"

laander avatar Jan 17 '19 09:01 laander

@laander That solves the issue with the arguments, but I think a modifier to let Vue do it would be a nice addition.

I think this modifier can be specially useful for wrapper components that need to emit most events they receive from their child component.

Vontus avatar Jan 17 '19 20:01 Vontus

I think this would be a cool addition

AlbertMarashi avatar Jan 21 '19 10:01 AlbertMarashi

+1

raisou avatar Jun 17 '19 14:06 raisou

@input="$emit('input', ...arguments)" works great, however @input.propagate would be an awesome addition

AlbertMarashi avatar Jun 18 '19 09:06 AlbertMarashi

nice!!! OPEN SOURCE FTW

lopugit avatar Sep 15 '19 09:09 lopugit

That's also great for keeping the whole app more maintainable

alecoscia avatar Sep 24 '19 12:09 alecoscia

I believe you can achieve this by adding v-on="$listeners" on a root element of the nested component?

muodov avatar Nov 11 '20 14:11 muodov

I believe you can achieve this by adding v-on="$listeners" on a root element of the nested component?

I didn't know that, thank you for the tip! The only problem I find is that you aren't able to select which events are being propagated to the parent, it just forwards every event from the nested component.

Vontus avatar Nov 24 '20 08:11 Vontus

@Vontus you can! Just wrap $listeners with your own computed property that filters the keys

muodov avatar Nov 24 '20 10:11 muodov

Hey, not considered anymore?

sinux-l5d avatar Oct 12 '21 22:10 sinux-l5d

Is anyone working on this? I'd love to see this feature

dospunk avatar Oct 22 '21 18:10 dospunk

I posted the same request back in 2018 for a bubble modifier, but it was rejected as syntax sugar: https://github.com/vuejs/vue/issues/7965

In Svelte you can just do <button on:click> to forward the event, so it would be really nice if you could just do <button @click> in Vue (or at least had a modifier).

nerdcave avatar Apr 16 '22 15:04 nerdcave

It seems like $listeners was removed in Vue 3. What's the recommended way for building a transparent wrapping component now?

bryanmylee avatar Aug 22 '22 23:08 bryanmylee

@bryanmylee Listeners are now in $attrs, and they begin with on (e.g., onClick).

tony19 avatar Aug 22 '22 23:08 tony19