vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
208.01k stars 33.69k forks source link

Modifier to propagate/forward events to parent #9325

Open Vontus opened 5 years ago

Vontus commented 5 years ago

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

lopugit commented 5 years ago

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

I do like having a dedicated keyword though

Vontus commented 5 years ago

@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.

lopugit commented 5 years ago

Isn't propagating arguments upwards what you want??

On Wed., 16 Jan. 2019, 6:50 pm Vontus <notifications@github.com 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 .

laander commented 5 years ago

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

@input="$emit('input', ...arguments)"
Vontus commented 5 years ago

@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.

AlbertMarashi commented 5 years ago

I think this would be a cool addition

raisou commented 5 years ago

+1

AlbertMarashi commented 5 years ago

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

lopugit commented 5 years ago

nice!!! OPEN SOURCE FTW

alecoscia commented 5 years ago

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

muodov commented 4 years ago

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

Vontus commented 3 years ago

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.

muodov commented 3 years ago

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

sinux-l5d commented 3 years ago

Hey, not considered anymore?

dospunk commented 3 years ago

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

nerdcave commented 2 years ago

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).

bryanmylee commented 2 years ago

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

tony19 commented 2 years ago

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

bersace commented 1 month ago

Transparent forwarding of event from an element to the component in svelte is very awesome.

I have a field component wich renders an input with a datalist. This breaks transparent event forwarding.

Could Vue 3 have something like <input v-on:click v-on:keyup /> ?

nmhungdev commented 1 month ago

Vue lacks this feature, but you can create a composable to achieve it. Check out my example for guidance.