-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
Conditional event binding #7349
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
Comments
Actually there's another, simple way how you can handle this case. You can pass computed property with your listeners object (or null if condition is not met) to |
maybe you need ? |
Yes, @sqal's solution is a good one and with inlining like @yyx990803's shows is close enough to what I had in mind. Thanks! This leads me to a deeper issue though: If a rebind happens (data change) and upon evaluation the condition changes (or more generally if the event spec object passed to v-on is different), existing event subscriptions are not cleaned up. They will still (hopefully) be disposed at the end of the component's lifecycle but not when they 'should' which is when v-on rebinds. This may be an edge case that does not have a large impact for most scenarios but just for reference: In my scenario I have a complex SVG and need to (optionally) attach mouse over/out handlers to specific elements based on some logic. A typical solution - and what I'm going to end up doing - is to set up one 'top level' event listener (per event type) and let events bubble up to it but to explain my motivation for trying it the Vue way first, there's quite a bit of processing that has to happen in my handlers which I had intended to pre-calculate and bake right into the event subscriptions itself so that the handlers have less to do (quicker and more fluid response) and are not invoked at all for elements that don't require it (as opposed to filtering this out relying on DOM queries in the handler). |
@vsevolodtrofimov the whole point was to avoid the event subscription from happening at all. Applying the condition in the handler does not satisfy this requirement. Please note the comments above as they do provide a satisfactory resolution. I am closing this issue to reflect that. |
Is it possible to pass |
With the suggested solution
Is there a way to apply modifiers like ".stop.prevent"? |
Hey @yyx990803 @vsevolodtrofimov The solution suggested here (using I'm getting this error: So looks like Vue is actually trying to fire the handler instead of unbinding the event 🤔 . |
@DawidMyslak v-on="condition ? { mouseover: handler } : {}" or, if your handler is called v-on="condition ? { mouseover } : {}" |
Nice one @pbastowski ! |
Thank you guys! |
You may want to wrap with inline function if you are calling a handler with custom data. Something like this
|
This should be in Vue docs |
Is there a way to combine this with |
You can use https://vuejs.org/v2/guide/render-function.html#Event-amp-Key-Modifiers <button v-on="{ '~click': () => foo = new Date() }">Trigger only once</button> |
One question on this, will there be memory leaks or event listeners not removed when I do the following, and the condition regularly changes?
So in short, does the |
@dietergeerts it does. |
Does this work with native events? I couldn't get it working with |
FYI. Since 2.6 (not released yet) you will be able to apply a conditional event binding as follows: <div @[event]="handler" /> While |
@Justineo That's great, but I just tried the beta and it doesn't seem to work with modifiers (of any type) either. Has that not been implemented yet? Is it planned? |
@AlansCodeLog it should work with all modifiers. If it's not working you should open a new issue with a reproduction. |
@yyx990803 Okay, I'll see if I can reproduce it. |
I have opened an issue here: #9417 |
Browser JavaScript version
|
@kieryk123 Can you provide a CodeSandbox link to look at? |
In my case, I was trying to do this on a disabled button element (via Vuetify), but apparently Chrome doesn't fire the necessary events, and the element should be wrapped in a div or similar to catch the event. |
Hello. // not working
v-on="{ [condition ? 'click.stop' : 'click'] : eventfunc }"
// or
// error
v-on="{ condition ? 'click.stop' : 'click' : eventfunc }" Is there any other solution? |
Here is the trick for native events (using Vue v2.6.11):
|
@Justineo was this syntax added to Vue? |
@AndrewBogdanovTSS have a look at this fiddle https://jsfiddle.net/pbastowski/v0wt5qpo/27/ The syntax works just fine for normal and native clicks. Note that |
@pbastowski simple string is working, yes, but what I need is to be able to resolve the value of event based on some reactive data, so I need something like
and such syntax doesn't work for me |
@AndrewBogdanovTSS Just move your logic to a computed, see the updated example here https://jsfiddle.net/pbastowski/v0wt5qpo/63/ |
@AndrewBogdanovTSS another solution:
Just make sure to not use spaces / quotes in the event name (why there's text in antiquotes) |
What problem does this feature solve?
Right now if we want an event handler to run conditionally we need to place the condition in the event handler which means that the event is still subscribed to and we pay the memory allocation fee for the event subscription (the underlying addEventListener and corresponding handler).
In some scenarios this is a pain. For example: say I've got mouse events (mouseover, mouseout) that are only meaningful on devices that actually have a pointer/mouse and so are meaningless on mobile and touch devices.
Right now, I'd have to create the event subscriptions and add the condition in the handler (or in this case no need even for that as the events would never fire) BUT I've still attached these handlers and allocated memory for them - which especially on memory constrained platforms like mobile browsers is a waste.
By making the event subscription itself conditional we can avoid this.
What does the proposed API look like?
In its simplest form we could just examine the handler provided and if falsy (or just null) short-circuit the event subscription and NOT apply the underlying addEventListener operation.
This way the condition can appear in the event binding declaration itself:
The text was updated successfully, but these errors were encountered: