Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In 2.5.1+, v-model cannot be combined with v-on="$listeners" #7042

Closed
chrisvfritz opened this issue Nov 10, 2017 · 4 comments
Closed

In 2.5.1+, v-model cannot be combined with v-on="$listeners" #7042

chrisvfritz opened this issue Nov 10, 2017 · 4 comments

Comments

@chrisvfritz
Copy link
Contributor

chrisvfritz commented Nov 10, 2017

Version

2.5.1+

Reproduction link

https://jsfiddle.net/bvyo2yra/

Steps to reproduce

See the minimal reproduction.

What is expected?

Previous to 2.5.1, v-on="$listeners" could be used in combination with more specific event handlers to create components that could transparently pass events to an element inside them. This worked because the more specific listeners (e.g. @input="$emit('input', $event.target.value)) were called after the more generic listeners with v-on="$listeners.

What is actually happening?

In 2.5.1, these higher priority listeners are now triggered first, so that if the listener sets a value, it will set the correct value, then the incorrect value, breaking v-model.


The breaking change was made to solve another issue, so it's probably not ideal to just revert the change. And actually, even the previous behavior was slightly undesirable, as it emitted the same event twice.

To fix both issues, I would actually expect the more specific event binding (e.g. @input) to replace the listener of the same name from v-on with the object syntax. The more specific listener would then take responsibility for emitting an event at the correct time. That allows the user full, explicit control over the order in which local handlers and handlers from the parent are called.

How does that sound to others?

@yyx990803
Copy link
Member

The replacing behavior would also be a breaking change though. I think preserving both is more semantically correct, and among the two, the current behavior in 2.5.1+ is the more reasonable (disregarding combined usage with v-model).

I think the goal really should be how can we make v-model and v-on="$listeners" work together while retaining the semantically correct behavior. There is currently a workaround I mentioned here, although it's not very straightforward and requires understanding of the internals.

@yyx990803 yyx990803 removed the bug label Nov 13, 2017
@chrisvfritz
Copy link
Contributor Author

Yeah, I'm not a fan of the workaround - it feels a bit hacky. What would you think about suggesting the following pattern instead?

<input 
  :value="value" 
  v-on="{
    ...$listeners,
    input: event => $emit('input', event.target.value)
  }"
>

@yyx990803
Copy link
Member

@chrisvfritz that's actually reasonable. It's explicitly overwriting the parent input listener.

@chrisvfritz
Copy link
Contributor Author

Excellent. I've updated the docs and this issue can probably be closed, but I agree that long-term, it really would be nice for v-model listeners just automatically work.

Ideally, v-model listeners on components could:

  1. Check if the emitted payload is an Event...
    • If yes, check event.target.tagName to choose the appropriate element listener
    • If no, use the normal behavior for v-model on components, where the payload is assumed to be the new value

mauritsderuiter95 added a commit to mauritsderuiter95/vue-argon-design-system that referenced this issue Dec 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants