Svelte is an up and coming front end framework for developing front end web apps.
It’s simple to use and lets us create results fast.
In this article, we’ll look at how to handle DOM events in Svelte components.
Events
We can use the on: directive to handle events. For instance, we can write the following to get the mouse position as we move our mouse around the screen:
App.svelte :
<script>
let pos = { x: 0, y: 0 };
const handleMousemove = event => {
pos.x = event.clientX;
pos.y = event.clientY;
};
</script>
<style>
div {
width: 100vw;
height: 100vh;
}
</style>
<div on:mousemove={handleMousemove}>
The mouse position is {pos.x} x {pos.y}
</div>
In the code above, we have on:mousemove={handleMousemove} to attach the handleMousemove handler to our div.
The handleMousemove function has the event parameter, which is the MouseEvent object.
Therefore, we can access the mouse position with the clientX and clientY properties for the x and y position of the mouse respectively.
In the end, we display them on the screen.
Event handlers can also be declared inline as follows:
App.svelte :
<script>
let pos = { x: 0, y: 0 };
</script>
<style>
div {
width: 100vw;
height: 100vh;
}
</style>
<div on:mousemove={event => {
pos.x = event.clientX;
pos.y = event.clientY;
}}>
The mouse position is {pos.x} x {pos.y}
</div>
Or we can put them between quotes as follows:
App.svelte :
<script>
let pos = { x: 0, y: 0 };
</script>
<style>
div {
width: 100vw;
height: 100vh;
}
</style>
<div on:mousemove="{event => {
pos.x = event.clientX;
pos.y = event.clientY;
}}">
The mouse position is {pos.x} x {pos.y}
</div>
The quotes provide syntax highlighting in some environments, but they’re optional.
Inline event handler doesn’t impact the performance of the app since Svelte will optimize it by not attaching and detaching on the fly.
Modifiers
DOM event directives can have modifiers attached to them to change their behavior.
For instance, we can add the once modifier to the on:click directive to only listen to mouse click of an element once:
App.svelte :
<script>
const handleClick = () => {
alert("alert");
};
</script>
<button on:click|once={handleClick}>
Click Me Once
</button>
The once modifier in the code above only runs the handleClick handler once, so if we click the button again, it’ll run nothing.
Other modifiers include:
preventDefault— callsevent.preventDefaultbefore running the handlerstopPropagation— callsevent.stopPropagationto prevent the event from reaching the next elementpassive— improves scrolling performance on touch or wheel eventscapture— fires handlers during the capture phase instead of the bubbling phaseself— only trigger handler ifevent.targetis the element itself.
They can also be chained together like on:click|once|self .
Photo by Marvin Meyer on Unsplash
Component Events
Components can also dispatch events. For instance, we can write the following code to dispatch an event from a child to a parent:
App.svelte :
<script>
import Button from "./Button.svelte";
const handleGreet = event => {
alert(event.detail.text);
};
</script>
<Button on:greet={handleGreet} />
Button.svelte :
<script>
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
const greet = () => {
dispatch("greet", {
text: "Hello Mary"
});
};
</script>
<button on:click={greet}>
Send Greeting
</button>
In Button, we create the dispatch constant with the createEventDispatcher function. dispatch is a function, which we call with the event name and the payload to send with the event emission as the arguments.
Then in App , we listen to the greet event emitted from Button by attaching the handleGreet event listener to the on:greet directive.
When handleGreet runs after the greet event is emitted, then the event object has the data sent with the event emission and we retrieved it with event.detail.text .
Therefore, when we click the Send Greeting button, we see ‘Hello Mary’ displayed in an alert box.
Event Forwarding
Component events don’t bubble like DOM events. To forward them to another component, we can add a forward function, which calls dispatch .
Then we can listen to the event in the component where the event is forwarded to.
For instance, we can write:
Button.svelte :
<script>
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
const greet = () => {
dispatch("greet", {
text: "Hello Mary"
});
};
</script>
<button on:click={greet}>
Send Greeting
</button>
Parent.svelte :
<script>
import Button from "./Button.svelte";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
const forward = () => {
dispatch("greet", event.detail);
};
</script>
<Button on:greet />
App.svelte :
<script>
import Parent from "./Parent.svelte";
const handleGreet = event => {
alert(event.detail.text);
};
</script>
<Parent on:greet={handleGreet} />
In the code above, Button.svelte emits the greet event, then the Parent.svelte component forwards the event, then App.svelte listens to the greet event.
In Parent.svelte ,
<Button on:greet />
is the same as:
<Button on:greet={forward} />
DOM Event Forwarding
We can forward DOM events like component events. For instance, we can write:
Button.svelte :
<button on:click>
Send Greeting
</button>
Parent.svelte :
<script>
import Button from "./Button.svelte";
</script>
<Button on:click />
App.svelte :
<script>
import Parent from "./Parent.svelte";
const handleClick = event => {
alert("Hello");
};
</script>
<Parent on:click={handleClick} />
The code above forwards the click event from Buttonto Parent and Parent to App .
Therefore, we’ll see a ‘Hello’ alert displayed on the screen when we click the Send Greeting button.
Conclusion
Svelte components and DOM elements can have event handlers attached to them.
We listen to events using the on: directives with modifiers.
Events can be forwarded with the on: directive without any value set to it.