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.preventDefault
before running the handlerstopPropagation
— callsevent.stopPropagation
to 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.target
is 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 Button
to 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.