Svelte: Add support for modifiers to event handlers

Created on 9 Jan 2018  Â·  8Comments  Â·  Source: sveltejs/svelte

A (relatively) easy and useful enhancement to Svelte would be to adopt one or more of the 5 Vue ideas in this area.

i.e.

  1. .stop
  2. .prevent
  3. .capture
  4. .self
  5. .once

"It is a very common need to call event.preventDefault() or event.stopPropagation() .... "
https://vuejs.org/v2/guide/events.html#Event-Modifiers

```



...


...

```

proposal

Most helpful comment

Finally added in 2.15 — demo here.

We can use the preventDefault, stopPropagation, once, capture and passive modifiers.

passive only applies to touch/wheel events, and is applied automatically where it makes sense.

once and passive aren't implemented in legacy mode — the compiler will throw an error in this situation. That could be fixed in future.

All 8 comments

I like those. At present you can do

<a on:click="event.stopPropagation()"></a>

<!-- the submit event will no longer reload the page -->
<form on:submit="event.preventDefault()"></form>

but that's it.

One consideration that applies to any syntax change is that we wouldn't then be able to use that syntax for anything else, e.g. if we want to do something like namespaced event handlers in future...

<input on:keys.tab='advance()' on:keys.enter='submit()' on:keys.escape='cancel()'>

<script>
  function keyHandler(which) {
    return (node, callback) => {
      function handleKeydown(event) {
        if (event.which !== which) return;
        callback(event);
      }

      node.addEventListener('keydown', handleKeydown);

      return {
        teardown() {
          node.removeEventListener('keydown', handleKeydown);
        }
      };
    };
  }

  export default {
    events: {
      keys: {
        tab: keyHandler(9),
        enter: keyHandler(13),
        escape: keyHandler(27)
      }
    }
  };
</script>

...we'd be stuffed. (This is one reason I prefer to move at a speed people often find excruciatingly slow when it comes to introducing new APIs, by the way! These conflicts often reveal themselves only gradually, in my experience.)

Indeed, I'm not sure that a namespace-like syntax makes that much sense in this context. Maybe there's a different character we could use — maybe the colon again?

<!-- modifiers can be chained -->
<a on:click:stop:prevent="doThat()"></a>

(This is one reason I prefer to move at a speed people often find excruciatingly slow when it comes to introducing new APIs, by the way! These conflicts often reveal themselves only gradually, in my experience.)

Good point. You're the man Rich and also have the experience to know what is best. Slow is good!

Indeed, I'm not sure that a namespace-like syntax makes that much sense in this context

I'd agree. Re. your example, interestingly was going to add the link to the key modifiers in this item but didn't, it seems elegant too?
https://vuejs.org/v2/guide/events.html#Key-Modifiers

Would definitely be keen to move forward with this in the near future, as it comes up from time to time. Had a thought — would it be crazy to use the pipe character here?

<a on:click|stop|prevent="doThat()"></a>

It sort of works as a metaphor for what's happening — the click event has to flow through the 'stop' and 'prevent' steps on the way to doThat — and avoids the problem of overloading the : or . characters.

I think that seems nice - it would be good to use a different character than colon for this. One question I do have (I don't know whether we'd need to consider this right away, but it might make sense to) is whether/how we want to support modifiers on custom DOM events. Or (somewhat more tenuous) on component events.

Easiest thing would definitely be to disallow modifiers for custom and component events. I guess in theory you could support them in custom events like this?

events: {
  longpress: (node, callback, modifiers) => {
    // modifiers is an array like ['stop', 'capture']
    // ...
  }
}

I would definitely file that under YAGNI to begin with though.

Finally added in 2.15 — demo here.

We can use the preventDefault, stopPropagation, once, capture and passive modifiers.

passive only applies to touch/wheel events, and is applied automatically where it makes sense.

once and passive aren't implemented in legacy mode — the compiler will throw an error in this situation. That could be fixed in future.

Feature Request: Key Modifiers for event handlers

<a on:keyup.delete|preventDefault={onDeleteDoStuff}

An old, closed issue is not the best place to raise a feature request.

I'm also not particularly sold on the idea of modifiers for key events - I think I'd prefer just doing this manually, since it's easy to have inline expressions in the handler that test for key codes. If you want to have separate handlers for different keys, that would also be made a little tidier with the proposal in #2688 / #2709.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matt3224 picture matt3224  Â·  3Comments

ricardobeat picture ricardobeat  Â·  3Comments

rob-balfre picture rob-balfre  Â·  3Comments

sskyy picture sskyy  Â·  3Comments

mmjmanders picture mmjmanders  Â·  3Comments