Events
As we've briefly seen already, you can listen to any event on an element with the on: directive:
<script>
let m = { x: 0, y: 0 };
function handleMousemove(event) {
m.x = event.clientX;
m.y = event.clientY;
}
</script>
<style>
div { width: 100%; height: 100%; }
</style>
<div on:mousemove={handleMousemove}>
The mouse position is {m.x} x {m.y}
</div>
See this list for list of all events available on the DOM.
Inline Handlers
You can also declare event handlers inline:
<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
The mouse position is {m.x} x {m.y}
</div>
The quote marks are optional, but they're helpful for syntax highlighting in some environments.
Event Modifiers
DOM event handlers can have modifiers that alter their behaviour. For example, a handler with a once modifier will only run a single time:
<script>
function handleClick(e) { // you can access the event and event.target
alert('no more alerts')
}
</script>
<button on:click|once={handleClick}>
Click me
</button>
The full list of modifiers:
- preventDefault — calls event.preventDefault() before running the handler. Useful for client-side form handling.
- 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
Components can also dispatch events. To do so, they must create an event dispatcher. This event is custom made by you, so you can use any name for event name, in this example we use 'message' for event name. createEventDispatcher must be called when the component is first instantiated — you can't do it later inside e.g. a setTimeout callback. This links dispatch to the component instance.
<script>
// Inner.svelte
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function sayHello() {
dispatch('message', {
text: 'Hello!'
});
}
</script>
After that we can use the component in our main app. We can alert text we got from component, that is contained in event.detail. Notice the event name in Inner component is 'message', you can use any name it's not predefined name.
<script>
import Inner from './Inner.svelte';
function handleMessage(ev) {
alert(ev.detail.text); // Hello! from Inner.svelte
}
</script>
<Inner on:message={handleMessage}/>
Event Forwarding
Unlike DOM events, component events don't bubble. If you want to listen to an event on some deeply nested component, the intermediate components must forward the event. For example we have app.svelte for main app, inner.svelte and outer.svelte for component will be used in main app. Outer will contain Inner component (App <- Outer <- Inner). When Inner dispatch event, event cannot be used in main app, unless we do event forwarding in Outer component. This is example of event forwarding in outer.svelte. Notice the <Inner on:message/> instead of just <Inner/>
<script>
import Inner from './Inner.svelte';
</script>
<Inner on:message/>
DOM Event Forwarding
Event forwarding works for DOM events too. For example if we made custom button like this
<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>
<button>Click me</button>
Then we use custom button in main app
<script>
import CustomButton from './CustomButton.svelte';
function handleClick() {
alert('clicked');
}
</script>
<CustomButton on:click={handleClick}/>
This wont work, as you notice in CustomButton.svelte we haven't added event forwarding yet, so instead of using just <button>Click me</button>, we need to type <button on:click>Click me</button> as event forwarding.