DEV Community

Cover image for How to use events in Svelte
Marc
Marc

Posted on • Edited on • Originally published at marcradziwill.com

How to use events in Svelte

Intro to Svelte events

In my last article about Svelte, I talked about the advantages in general and how you can implement your first components, import them or display dynamic data. If you are new to Svelte you should read my article "Why you should try Svelte".


If you like this article, smile for a moment, share it, follow me, check out my RSS feed and subscribe to my newsletter.


Today we talk about the cosmos of events in Svelte. I will cover DOM Events, Custom Events or Component Events "and a bit about the tricky parts.".

Tl;dr

In this article, I cover Svelte events, their use cases, how you implement custom component events and how you can bubble them up the DOM.

I posted this article initially on my blog.


1. Built-In Event handlers

DOM Events

Event handlers are added to a component by on:{eventname} directive. To listen to the onclick event, you'll pass a function to the on:onclick attribute. You get the event object as an argument of your click handler.

<script>
  function handleClick(event) {
    console.log('whooohoooo click event listener worked');
  }
</script>
<button on:click="{handleClick}">Click me</button>
Enter fullscreen mode Exit fullscreen mode

ℹ️ Performance hint

As the compiler takes care of the JavaScript generation, it also handles your coding style. In some frameworks, it's recommended to avoid inline event handlers for performance reasons. The compiler takes care of this. I got used to avoiding inline functions, therefore you won't see them in my examples. But feel free to use them in Svelte if you like.

Event modifiers

DOM events can have an event modifier. You can use them to tell the compiler to perform additional logic.

List of event modifiers

  • preventDefault — "calls event.preventDefault() before running the handler. Useful for client-side form handling, for example."
  • stopPropagation — "calls event.stopPropagation(), preventing the event reaching the next element"
  • passive — "improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)"
  • capture — "fires the handler during the capture phase instead of the bubbling phase ()"
  • once — "remove the handler after the first time it runs"
  • self — "only trigger handler if event.target is the element itself"

Component events

You can create custom events in components and dispatch them. To do so you need to create a custom event dispatcher with the building function createEventDispatcher. createEventDispatcher has to be called when the component is instantiated for the first time.

If you not familiar with event bubble and capture I recommend you to check out that topic as I don't cover it in my post.

As soon as you want to trigger the event you use the dispatch function. This function takes a string and object as arguments. The string identifies the event and the object is optional data that is available on the event object.

CustomEvent.svelte

<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();

  // trigger event and send object
  function sayHello() {
    dispatch('eventName', {
      text: 'nice event',
    });
  }
</script>

<button on:click="{sayHello}">Click for your custom event</button>
Enter fullscreen mode Exit fullscreen mode

App.svelte

<script>
  import CustomEvent from './components/CustomEvent.svelte';
</script>

<CustomEvent on:eventName={(event, args) => { console.log(event, args); }} />
Enter fullscreen mode Exit fullscreen mode

2. Event forwarding

If you write a custom component event you have to keep in mind, that they don't bubble up the DOM like DOM events itself. If you want to listen to an event that a nested component dispatched you to have to forward it from the intermediate components.

Web Performance Checklist

As you see below you Svelte has a shorthand for event forwarding. Your intermediate component forwards the event by using the same listener directive as before but without any event handler. In our case <CustomEvent on:eventName/> in Wrapper.svelte forwards the event triggered in CustomEvent.svelte.

App.svelte

<script>
  import Wrapper from './Wrapper.svelte';

  function handleEvent(event) {
    console.log(event);
  }
</script>

<Wrapper on:eventName="{handleEvent}" />
Enter fullscreen mode Exit fullscreen mode

Wrapper.svelte

<script>
  import CustomEvent from './CustomEvent.svelte';
</script>

<CustomEvent on:eventName />
Enter fullscreen mode Exit fullscreen mode

CustomEvent.svelte

<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();

  // trigger event and send object
  function sayHello() {
    dispatch('eventName', {
      text: 'nice event',
    });
  }
</script>

<button on:click="{sayHello}">Click for your custom event</button>
Enter fullscreen mode Exit fullscreen mode

DOM event forwarding

The event forwarding just presented can also be used for DOM events. If you have a custom component with a child that is listening to a DOM event, you can forward these events as well.

FancyImage.svelte

<style>
  img {
    width: 100%;
  }
</style>

<img
  on:mouseover
  src="https://images.unsplash.com/photo-1561303087-84f633edd5ea"
  alt="Photo by @sebastiandumitru on unsplash"
/>
Enter fullscreen mode Exit fullscreen mode

App.svelte

<script>
  import FancyImage from './FancyImage.svelte';

  function handleHover() {
    alert('clicked');
  }
</script>

<FancyImage on:mouseover="{handleHover}" />
Enter fullscreen mode Exit fullscreen mode

4. What's next?

You find all the resources for this article on GitHub. Feel free to check it out, try some stuff or fork it.

Now you should be able to use events in Svelte like a pro! If you want to dive deeper, I recommend taking an hour or two of your time and going through the official tutorial.

If you like this article, smile for a moment, share it, follow me, check out my RSS feed and subscribe to my newsletter.

Cheers Marc

Top comments (0)