Skip to content

Bindings

Two-way binding is sugar over value + event

Section titled “Two-way binding is sugar over value + event”

Normally data flows one way: state → the DOM. A binding adds the reverse edge, so a form element also writes back to state. bind:value is shorthand for “set the input’s value from this state, and update this state on input.”

<script>
let name = $state('');
</script>
<input bind:value={name} />
<p>Hello {name}</p>
<!-- Equivalent, written by hand:
<input value={name} oninput={(e) => name = e.currentTarget.value} /> -->

The binding keeps the two in sync automatically. It works on any input-like element: bind:value for text/number/select, bind:checked for checkboxes, bind:files for file inputs.

Radio buttons and checkbox groups that share one piece of state use bind:group — Svelte wires the whole set to a single variable.

<script>
let flavor = $state('vanilla'); // radios: a single value
let toppings = $state([]); // checkboxes: an array
</script>
<label><input type="radio" bind:group={flavor} value="vanilla" /> Vanilla</label>
<label><input type="radio" bind:group={flavor} value="chocolate" /> Chocolate</label>
<label><input type="checkbox" bind:group={toppings} value="nuts" /> Nuts</label>
<label><input type="checkbox" bind:group={toppings} value="cherry" /> Cherry</label>

For radios, flavor holds the selected value; for checkboxes, toppings is an array of the checked values.

bind:this for element and component references

Section titled “bind:this for element and component references”

To get a reference to the actual DOM node (or a component instance), use bind:this. It’s set after the element mounts — read it in an effect or event handler, not during initial render.

<script>
let canvas = $state(); // will hold the DOM node
$effect(() => {
const ctx = canvas.getContext('2d'); // safe: runs after mount
ctx.fillRect(0, 0, 50, 50);
});
</script>
<canvas bind:this={canvas} width="200" height="200"></canvas>

A parent can bind to a child component’s prop when the child declares that prop as $bindable() (from the reactivity module). This creates two-way data flow across the component boundary.

Child.svelte
<script>
let { value = $bindable() } = $props();
</script>
<input bind:value={value} />
Parent.svelte
<script>
import Child from './Child.svelte';
let text = $state('hi');
</script>
<Child bind:value={text} /> <!-- parent's text and child's value stay in sync -->

Use component bindings deliberately — they let a child mutate a parent’s state, which is powerful but can obscure data flow if overused. Props-down/events-up is often clearer for anything beyond simple form controls.

What is `bind:value={name}` shorthand for?
What do you use for a set of radio buttons sharing one selected value?
When is a `bind:this` reference available?
What must a child declare to allow a parent to `bind:` to its prop?