Bindings
bind:value={cell} is two-way sugar that wires a form control into a reactive state cell. It combines:
- a property bind — when the cell changes, write the new value to the input’s DOM property
- an event listener — when the user types, write the input’s current value back into the cell
You could write both halves yourself, but bind: is shorter and ensures the two stay in sync.
bind:value
For <input>, <textarea>, and <select>:
component LoginForm {
state email = ""
state password = ""
view {
<form>
<input bind:value={email} type="email" placeholder="email" />
<input bind:value={password} type="password" placeholder="password" />
</form>
}
}
Without bind:, the equivalent is:
<input value={email} oninput={e => email = e.target.value} />
Same behavior, more keystrokes.
<select>
component Picker {
state pick = "a"
view {
<select bind:value={pick}>
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</select>
<p>you picked {pick}</p>
}
}
bind:value on <select> listens to change and reads e.target.value.
<textarea>
<textarea bind:value={notes} rows="6" />
Listens to input. Same as the <input> case.
bind:checked
For checkboxes and radio buttons:
component Settings {
state notifications = true
state darkMode = false
view {
<label>
<input type="checkbox" bind:checked={notifications} />
notifications
</label>
<label>
<input type="checkbox" bind:checked={darkMode} />
dark mode
</label>
}
}
bind:checked listens to change and reads e.target.checked (a boolean — no string coercion).
Rules
A handful of rules the compiler enforces:
-
The bound expression must be a writable reactive lvalue. Typically a
stateidentifier or a reactiveprop:state draft = "" <input bind:value={draft} /> ✓ let raw = "" <input bind:value={raw} /> ✗ — let is not reactive -
You can’t combine
bind:valuewith an explicitvalue=oroninput=on the same element. It’s a parse error. Pick one. -
bind:valuechooses the right event for the element:inputfor<input>/<textarea>,changefor<select>.
Property, not attribute
Internally bind: emits a property bind, not an attribute bind. The runtime sets el.value = ... or el.checked = ... directly on the DOM node.
This matters because setAttribute("value", "...") only changes the initial value of an input — it does not overwrite what the user has typed. Property assignment does. So when you do draft = "preset" programmatically, the user’s already-typed text gets replaced as expected.
Other bindings?
Today, only bind:value and bind:checked are implemented. Bindings for group, files, bind:this, dimension bindings (clientWidth, etc.), media bindings — none of those are wired up yet. If you need them, attach the listener manually with an oninput / onchange handler and read the property off e.target.
See also
- Components — declaring
statecells. - Events — what
bind:desugars to.