You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/documentation/docs/99-legacy/10-legacy-on.md

137 lines
3.6 KiB

---
title: on:
---
In runes mode, event handlers are just like any other attribute or prop.
In legacy mode, we use the `on:` directive:
```svelte
<!--- file: App.svelte --->
<script>
let count = 0;
/** @param {MouseEvent} event */
function handleClick(event) {
count += 1;
}
</script>
<button on:click={handleClick}>
count: {count}
</button>
```
Handlers can be declared inline with no performance penalty:
```svelte
<button on:click={() => (count += 1)}>
count: {count}
</button>
```
Add _modifiers_ to element event handlers with the `|` character.
```svelte
<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` — calls `event.preventDefault()` before running the handler
- `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
- `stopImmediatePropagation` - calls `event.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 set `passive: false`
- `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
- `trusted` — only trigger handler if `event.isTrusted` is `true`. 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.
```svelte
<button on:click>
The component itself will emit the click event
</button>
```
It's possible to have multiple event listeners for the same event:
```svelte
<!--- file: App.svelte --->
<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>
```
## Component events
Components can dispatch events by creating a _dispatcher_ when they are initialised:
```svelte
<!--- file: Stepper.svelte -->
<script>
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`](https://developer.mozilla.org/en-US/docs/Web/API/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:
```svelte
<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.
> [!NOTE]
> If you're planning an eventual migration to Svelte 5, use callback props instead. This will make upgrading easier as `createEventDispatcher` is deprecated:
>
> ```svelte
> <!--- file: Stepper.svelte --->
> <script>
> export let decrement;
> export let increment;
> </script>
>
> <button on:click={decrement}>decrement</button>
> <button on:click={increment}>increment</button>
> ```