Component Communication
Props (Chapter 6) send data down. To send something back up — a click, a deletion, a chosen value — Svelte 5's primary approach is a callback prop: the parent passes a function down as a prop, and the child calls it. This is exactly React's model (Project 1's todo delete), and a notable shift from Svelte 4's event system.
Callback Props — Child Calls a Function
onDelete is just another prop — a function. The child calls onDelete(id) when its button is clicked, and the parent's removeTodo receives the id. There's no special "emit" mechanism (unlike Angular's @Output or Vue's defineEmits) — it's a plain function passed as a prop, identical to how React does it. Naming it onSomething is the convention, matching the event-handler naming.
createEventDispatcher() plus dispatch('delete', id) in the child and on:delete={handler} in the parent — a custom-event system much like Angular's @Output. Svelte 5 removed this in favor of callback props, simplifying the model to match React's. If you see createEventDispatcher or on:customEvent on a component, that's Svelte 4 code.
Multiple Callbacks
A component takes as many callback props as it needs, each a separate function. This scales cleanly — a dialog with onSave and onCancel, a form with onSubmit and onReset — all just functions passed down, with payloads passed as arguments when calling them.
$bindable — Two-Way Component Binding
Sometimes you want genuine two-way binding on a custom component — like a reusable input where the parent uses bind:value directly on it. The $bindable() rune marks a prop as bindable from the parent:
$bindable('') declares value as a prop the parent can two-way bind (with a default of ''). The child binds it to its real input; the parent uses bind:value={name} on the component itself, and changes flow both ways automatically. This is Svelte's equivalent of Vue's defineModel / v-model on a component, and Angular's value/valueChange two-way convention.
bind: ergonomics on a component, like a reusable form control. Most communication is callback props; $bindable is the more specialized tool, and Svelte deliberately requires opting in (a prop isn't bindable unless declared so).
$bindable, the one-way rule from Chapter 6 holds: the child reports upward via a callback and lets the parent own the source of truth. $bindable is the deliberate exception, used sparingly — not a license to mutate ordinary props.
| Svelte 5 | React | Vue | Angular |
|---|---|---|---|
| onDelete prop (a function) | callback prop onDelete | defineEmits + emit | @Output + emit |
| onDelete(id) | onDelete(id) | emit('delete', id) | this.delete.emit(id) |
| $bindable + bind:value | value + onChange props | defineModel / v-model | [(value)] |
Coding Challenges
Build a TodoItem component with id/text props and an onDelete callback prop. The parent holds a $state array of todos, renders one TodoItem each (keyed), and removes the matching todo when onDelete fires.
📄 View solutionBuild a ConfirmBar component with onConfirm and onCancel callback props (two buttons), and use it in a parent that logs which action was taken.
📄 View solutionBuild a CustomInput component exposing a $bindable value prop, then use bind:value on it in a parent and display the bound value live.
📄 View solutionChapter 7 Quick Reference
- Callback prop — pass a function down (
onDelete); the child calls it (= React's model) - No special emit mechanism — it's a plain function prop, unlike Angular's
@Output/ Vue'sdefineEmits - Name callbacks
onSomething; pass payloads as arguments when calling - $bindable(default) — marks a prop as two-way bindable, so the parent can use
bind:on the component - Use callbacks for events (the common case);
$bindableonly for genuine two-way control bindings - Svelte 5 dropped Svelte 4's
createEventDispatcherin favor of callback props - Next chapter: snippets and slots — Svelte's content-projection model