Deprecated: Use callback props and/or the $host() rune instead. See the migration guide for details.
Creates an event dispatcher that can be used to dispatch component events. Event dispatchers create CustomEvent instances that do not bubble.
Signature
function createEventDispatcher<
EventMap extends Record<string, any> = any
>(): EventDispatcher<EventMap>
return
EventDispatcher<EventMap>
An event dispatcher function
EventDispatcher
interface EventDispatcher<EventMap extends Record<string, any>> {
<Type extends keyof EventMap>(
...args: null extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions]
: undefined extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions]
: [type: Type, parameter: EventMap[Type], options?: DispatchOptions]
): boolean;
}
The event detail data. Type depends on the event type in the EventMap
Event optionsWhether the event can be cancelled with event.preventDefault()
Returns false if the event was cancelled with preventDefault(), otherwise true
Usage
Basic Event Dispatch
Create and dispatch simple events:
<!-- ChildComponent.svelte -->
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleClick() {
dispatch('message', { text: 'Hello!' });
}
</script>
<button onclick={handleClick}>
Send message
</button>
<!-- ParentComponent.svelte -->
<script>
import ChildComponent from './ChildComponent.svelte';
function handleMessage(event) {
console.log(event.detail.text); // 'Hello!'
}
</script>
<ChildComponent on:message={handleMessage} />
Typed Event Dispatcher
Type your events for better IDE support and type safety:
// ChildComponent.svelte
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
loaded: null; // no detail argument
change: string; // detail argument of type string (required)
optional: number | null; // optional detail argument
submit: { name: string; email: string }; // object detail
}>();
// TypeScript enforces correct usage:
dispatch('loaded'); // ✓ OK
dispatch('change', 'new value'); // ✓ OK
dispatch('change'); // ✗ Error: missing required detail
dispatch('optional', 42); // ✓ OK
dispatch('optional'); // ✓ OK
dispatch('submit', { name: 'John', email: 'john@example.com' }); // ✓ OK
Cancelable Events
Create events that can be cancelled:
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleSubmit() {
// Dispatch cancelable event
const cancelled = !dispatch('submit', { data: 'value' }, { cancelable: true });
if (cancelled) {
console.log('Submit was cancelled');
return;
}
console.log('Submit was not cancelled');
}
</script>
<button onclick={handleSubmit}>
Submit
</button>
Parent component:
<script>
import ChildComponent from './ChildComponent.svelte';
function handleSubmit(event) {
if (event.detail.data === 'invalid') {
event.preventDefault();
}
}
</script>
<ChildComponent on:submit={handleSubmit} />
Event Forwarding
Forward events from child components:
<!-- Button.svelte -->
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<button onclick={() => dispatch('click')}>
<slot />
</button>
<!-- MiddleComponent.svelte -->
<script>
import Button from './Button.svelte';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleClick() {
// Re-dispatch the event
dispatch('click');
}
</script>
<Button on:click={handleClick}>Click me</Button>
Or use the shorthand syntax:
<!-- MiddleComponent.svelte -->
<script>
import Button from './Button.svelte';
</script>
<!-- Forward the click event automatically -->
<Button on:click />
Event Characteristics
No Bubbling
Unlike DOM events, component events created with createEventDispatcher do not bubble:
<!-- Events only go one level up -->
<Grandparent>
<Parent>
<Child /> <!-- Event dispatched here -->
</Parent> <!-- Must explicitly forward to reach Grandparent -->
</Grandparent>
CustomEvent Details
Dispatched events are CustomEvent instances:
<script>
function handleEvent(event) {
console.log(event instanceof CustomEvent); // true
console.log(event.detail); // your event data
console.log(event.bubbles); // false
console.log(event.cancelable); // depends on options
}
</script>
Migration to Svelte 5
In Svelte 5, component events are replaced with callback props:
<!-- Before (Svelte 4) -->
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleClick() {
dispatch('click', { data: 'value' });
}
</script>
<!-- After (Svelte 5) -->
<script>
let { onclick } = $props();
function handleClick() {
onclick?.({ data: 'value' });
}
</script>
Parent usage:
<!-- Before -->
<Component on:click={handleClick} />
<!-- After -->
<Component onclick={handleClick} />
Notes
- Must be called during component initialization
- Events do not bubble - they only go one level up
- Events are
CustomEvent instances
- The
detail property contains your event data
- Return value indicates whether the event was cancelled
- Unlike DOM events, component events are synchronous
- In Svelte 5, prefer callback props over
createEventDispatcher
See Also