$bindable — Zwei-Wege-Bindung
Normalerweise fließen Props nur nach unten. Mit $bindable öffnest du gezielt einen Rückkanal, sodass ein Kind einen Wert auch nach oben zurückschreiben kann.
Warum $bindable?
Props sind in Svelte 5 standardmäßig einweg: Die Eltern-Komponente gibt einen
Wert nach unten, das Kind liest ihn. Manchmal — vor allem bei Formular-Bausteinen — soll das
Kind den Wert aber auch ändern und die Änderung soll oben ankommen. Genau
dafür markierst du eine Prop mit $bindable().
<script lang="ts">
interface Props {
value: string;
}
// $bindable() macht die Prop zwei-Wege-fähig
let { value = $bindable() }: Props = $props();
</script>
<input bind:value />Durch value = $bindable() erlaubst du der Eltern-Komponente, mit bind:value zu koppeln. Du kannst auch einen Default mitgeben, falls nicht gebunden
wird:
// Mit Default-Wert, falls die Eltern nicht binden:
let { value = $bindable('') } = $props();Eltern binden mit bind:
Auf der Elternseite nutzt du das bind:-Präfix. Ab jetzt teilen sich Eltern-State
und Kind-Prop denselben Wert: Tippt der Nutzer im Kind, aktualisiert sich name in
den Eltern — und umgekehrt.
<script lang="ts">
import TextFeld from './TextFeld.svelte';
let name = $state('Anna');
</script>
<!-- bind: koppelt Eltern-State und Kind-Prop in BEIDE Richtungen -->
<TextFeld bind:value={name} />
<p>Hallo, {name}!</p>🛤️ Rails-Vergleich: form_with / Objekt-Binding
Das erinnert an form_with model: in Rails, wo Formularfelder an ein Objekt
gekoppelt sind. Der Unterschied: Rails bindet über einen Request-Zyklus (Submit → Controller → zurück). bind: in Svelte ist dagegen sofort und im Browser — jede Tasteneingabe ist unmittelbar auf beiden Seiten
sichtbar.
<%# Rails form_for bindet ein Objekt an Formularfelder %>
<%= form_with model: @user do |f| %>
<%= f.text_field :name %>
<%# Beim Submit landet der Wert in params[:user][:name],
der Controller schreibt ihn zurück ins @user-Objekt %>
<% end %>Live: Zwei-Wege-Bindung in Aktion
Svelte bringt bind:value für native Formularelemente von Haus aus mit — das ist
dieselbe Zwei-Wege-Mechanik, die $bindable für deine eigenen Komponenten
freischaltet. Tippe unten und beobachte, wie die Anzeige sofort mitläuft:
Der State steht direkt hier in der Seite — bind: hält Input und Anzeige synchron.
Wann NICHT binden
⚠️ Zwei-Wege-Bindung sparsam einsetzen
bind: ist bequem, macht den Datenfluss aber schwerer nachvollziehbar, weil
Änderungen aus beiden Richtungen kommen. Als Faustregel: Halte Daten einweg, wo es geht. Nutze $bindable nur für echte
Formular-Bausteine (eigenes Input, Slider, Toggle), bei denen der zurückgegebene Wert der Zweck der Komponente ist.
<!-- Einweg (Standard, meistens richtig): Kind kann nur LESEN -->
<Anzeige value={name} />
<!-- Zwei-Wege (nur wo nötig): Kind darf auch SCHREIBEN -->
<TextFeld bind:value={name} />🚫 Anti-Pattern
Verwende bind: nicht als Abkürzung, um Zustand zwischen Komponenten „irgendwie"
zu synchronisieren. Für Kind→Eltern-Kommunikation, die eher ein Ereignis ist (Speichern,
Löschen, Auswählen), nimm besser Callback-Props — dazu mehr in der nächsten
Lektion.
Zusammenfassung
💡 Das Wichtigste
let { value = $bindable() } = $props()macht eine Prop zwei-Wege-fähig.- Eltern koppeln mit
<Kind bind:value={...} />. - Native Elemente können
bind:valuedirekt — ohne$bindable. - Faustregel: Datenfluss einweg halten,
$bindablenur für Formular-Bausteine.
🎯 Probier es selbst
Ergänze die Demo um einen zweiten Input für einen gruss-Text (z. B. „Hallo",
„Servus"). Binde ihn mit bind:value und baue ihn in die Anzeige ein — etwa {gruss}, {name}!. Achte darauf, dass beide Inputs sofort
durchschlagen.