on:
In runes mode, event handlers are just like any other attribute or prop.
In legacy mode, we use the on:
directive:
<script> let count = 0; /** @param {MouseEvent} event */ function handleClick(event) { count += 1; } </script> <button on:click={handleClick}> count: {count} </button>
<script lang="ts"> let count = 0; function handleClick(event: MouseEvent) { count += 1; } </script> <button on:click={handleClick}> count: {count} </button>
Handlers can be declared inline with no performance penalty:
<button on:click={() => (count += 1)}> count: {count} </button>
Add modifiers to element event handlers with the |
character.
<form on:submit|preventDefault={handleSubmit}> <!-- the `submit` event's default is prevented, so the page won't reload --> </form>
The following modifiers are available:
preventDefault
— callsevent.preventDefault()
before running the handlerstopPropagation
— callsevent.stopPropagation()
, preventing the event reaching the next elementstopImmediatePropagation
- callsevent.stopImmediatePropagation()
, preventing other listeners of the same event from being fired.passive
— improves scrolling performance on touch/wheel events (Svelte will add it automatically where it’s safe to do so)nonpassive
— explicitly setpassive: false
capture
— fires the handler during the capture phase instead of the bubbling phaseonce
— remove the handler after the first time it runsself
— only trigger handler ifevent.target
is the element itselftrusted
— only trigger handler ifevent.isTrusted
istrue
. I.e. if the event is triggered by a user action.
Modifiers can be chained together, e.g. on:click|once|capture={...}
.
If the on:
directive is used without a value, the component will forward the event, meaning that a consumer of the component can listen for it.
<button on:click> The component itself will emit the click event </button>
It’s possible to have multiple event listeners for the same event:
<script> let count = 0; function increment() { count += 1; } /** @param {MouseEvent} event */ function log(event) { console.log(event); } </script> <button on:click={increment} on:click={log}> clicks: {count} </button>
<script lang="ts"> let count = 0; function increment() { count += 1; } function log(event: MouseEvent) { console.log(event); } </script> <button on:click={increment} on:click={log}> clicks: {count} </button>
Component events
Components can dispatch events by creating a dispatcher when they are initialised:
<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); </script> <button on:click={() => dispatch('decrement')}>decrement</button> <button on:click={() => dispatch('increment')}>increment</button>
<script lang="ts"> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); </script> <button on:click={() => dispatch('decrement')}>decrement</button> <button on:click={() => dispatch('increment')}>increment</button>
dispatch
creates a CustomEvent
. If a second argument is provided, it becomes the detail
property of the event object.
A consumer of this component can listen for the dispatched events:
<script> import Stepper from './Stepper.svelte'; let n = 0; </script> <Stepper on:decrement={() => n -= 1} on:increment={() => n += 1} /> <p>n: {n}</p>
Component events do not bubble — a parent component can only listen for events on its immediate children.
Other than once
, modifiers are not valid on component event handlers.
If you’re planning an eventual migration to Svelte 5, use callback props instead. This will make upgrading easier as
createEventDispatcher
is deprecated:Stepper<script> export let decrement; export let increment; </script> <button on:click={decrement}>decrement</button> <button on:click={increment}>increment</button>
<script lang="ts"> export let decrement; export let increment; </script> <button on:click={decrement}>decrement</button> <button on:click={increment}>increment</button>
Edit this page on GitHub llms.txt