Svelte • Template syntax
bind:
On this page
Data ordinarily flows down, from parent to child. The bind: directive allows data to flow the other way, from child to parent.
The general syntax is bind:property={expression}, where expression is an lvalue (i.e. a variable or an object property). When the expression is an identifier with the same name as the property, we can omit the expression — in other words these are equivalent:
<input bind:value={value} />
<input bind:value />Svelte creates an event listener that updates the bound value. If an element already has a listener for the same event, that listener will be fired before the bound value is updated.
Most bindings are two-way, meaning that changes to the value will affect the element and vice versa. A few bindings are readonly, meaning that changing their value will have no effect on the element.
Function bindings
You can also use bind:property={get, set}, where get and set are functions, allowing you to perform validation and transformation:
<input bind:value={
() => value,
(v) => value = v.toLowerCase()}
/>In the case of readonly bindings like dimension bindings, the get value should be null:
<div
bind:clientWidth={null, redraw}
bind:clientHeight={null, redraw}
>...</div>Function bindings are available in Svelte 5.9.0 and newer.
<input bind:value>
A bind:value directive on an <input> element binds the input’s value property:
<script lang="ts">
let let message: stringmessage = function $state<"hello">(initial: "hello"): "hello" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"hello">(initial: "hello"): "hello" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('hello');
</script>
<input bind:value={let message: stringmessage} />
<p>{let message: stringmessage}</p><script>
let let message: stringmessage = function $state<"hello">(initial: "hello"): "hello" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"hello">(initial: "hello"): "hello" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('hello');
</script>
<input bind:value={let message: stringmessage} />
<p>{let message: stringmessage}</p>In the case of a numeric input (type="number" or type="range"), the value will be coerced to a number:
<script lang="ts">
let let a: numbera = function $state<1>(initial: 1): 1 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<1>(initial: 1): 1 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(1);
let let b: numberb = function $state<2>(initial: 2): 2 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<2>(initial: 2): 2 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(2);
</script>
<label>
<input type="number" bind:value={let a: numbera} min="0" max="10" />
<input type="range" bind:value={let a: numbera} min="0" max="10" />
</label>
<label>
<input type="number" bind:value={let b: numberb} min="0" max="10" />
<input type="range" bind:value={let b: numberb} min="0" max="10" />
</label>
<p>{let a: numbera} + {let b: numberb} = {let a: numbera + let b: numberb}</p><script>
let let a: numbera = function $state<1>(initial: 1): 1 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<1>(initial: 1): 1 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(1);
let let b: numberb = function $state<2>(initial: 2): 2 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<2>(initial: 2): 2 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(2);
</script>
<label>
<input type="number" bind:value={let a: numbera} min="0" max="10" />
<input type="range" bind:value={let a: numbera} min="0" max="10" />
</label>
<label>
<input type="number" bind:value={let b: numberb} min="0" max="10" />
<input type="range" bind:value={let b: numberb} min="0" max="10" />
</label>
<p>{let a: numbera} + {let b: numberb} = {let a: numbera + let b: numberb}</p>If the input is empty or invalid (in the case of type="number"), the value is undefined.
Since 5.6.0, if an <input> has a defaultValue and is part of a form, it will revert to that value instead of the empty string when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is null or undefined.
<script lang="ts">
let let value: stringvalue = function $state<"">(initial: ""): "" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"">(initial: ""): "" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('');
</script>
<form>
<input bind:let value: stringvalue defaultValue="not the empty string">
<input type="reset" value="Reset">
</form><script>
let let value: stringvalue = function $state<"">(initial: ""): "" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"">(initial: ""): "" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('');
</script>
<form>
<input bind:let value: stringvalue defaultValue="not the empty string">
<input type="reset" value="Reset">
</form>Use reset buttons sparingly, and ensure that users won’t accidentally click them while trying to submit the form.
<input bind:checked>
Checkbox inputs can be bound with bind:checked:
<label>
<input type="checkbox" bind:checked={accepted} />
Accept terms and conditions
</label>Since 5.6.0, if an <input> has a defaultChecked attribute and is part of a form, it will revert to that value instead of false when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is null or undefined.
<script lang="ts">
let let checked: booleanchecked = function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(true);
</script>
<form>
<input type="checkbox" bind:let checked: booleanchecked defaultChecked={true}>
<input type="reset" value="Reset">
</form><script>
let let checked: booleanchecked = function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(true);
</script>
<form>
<input type="checkbox" bind:let checked: booleanchecked defaultChecked={true}>
<input type="reset" value="Reset">
</form>Use
bind:groupfor radio inputs instead ofbind:checked.
<input bind:indeterminate>
Checkboxes can be in an indeterminate state, independently of whether they are checked or unchecked:
<script lang="ts">
let let checked: booleanchecked = function $state<false>(initial: false): false (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<false>(initial: false): false (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(false);
let let indeterminate: booleanindeterminate = function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(true);
</script>
<form>
<input type="checkbox" bind:let checked: booleanchecked bind:let indeterminate: booleanindeterminate>
{#if let indeterminate: booleanindeterminate}
waiting...
{:else if let checked: booleanchecked}
checked
{:else}
unchecked
{/if}
</form><script>
let let checked: booleanchecked = function $state<false>(initial: false): false (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<false>(initial: false): false (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(false);
let let indeterminate: booleanindeterminate = function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(true);
</script>
<form>
<input type="checkbox" bind:let checked: booleanchecked bind:let indeterminate: booleanindeterminate>
{#if let indeterminate: booleanindeterminate}
waiting...
{:else if let checked: booleanchecked}
checked
{:else}
unchecked
{/if}
</form><input bind:group>
Inputs that work together can use bind:group:
<script lang="ts">
let let tortilla: stringtortilla = function $state<"Plain">(initial: "Plain"): "Plain" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"Plain">(initial: "Plain"): "Plain" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('Plain');
let let fillings: string[]fillings: string[] = function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state([]);
</script>
<h1>Customize your burrito</h1>
<!-- grouped radio inputs are mutually exclusive -->
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Plain" /> Plain</label>
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Whole wheat" /> Whole wheat</label>
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Spinach" /> Spinach</label>
<!-- grouped checkbox inputs populate an array -->
<label><input type="checkbox" bind:group={let fillings: string[]fillings} value="Rice" /> Rice</label>
<label><input type="checkbox" bind:group={let fillings: string[]fillings} value="Beans" /> Beans</label>
<label><input type="checkbox" bind:group={let fillings: string[]fillings} value="Cheese" /> Cheese</label>
<label><input type="checkbox" bind:group={let fillings: string[]fillings} value="Guac (extra)" /> Guac (extra)</label>
<p>Tortilla: {let tortilla: stringtortilla}</p>
<p>Fillings: {let fillings: string[]fillings.Array<string>.join(separator?: string): stringAdds all the elements of an array into a string, separated by the specified separator string.
join(', ') || 'None'}</p>
<style>
label {
display: block;
}
</style><script>
let let tortilla: stringtortilla = function $state<"Plain">(initial: "Plain"): "Plain" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<"Plain">(initial: "Plain"): "Plain" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state('Plain');
/** @type {string[]} */
let let fillings: never[]fillings = function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state([]);
</script>
<h1>Customize your burrito</h1>
<!-- grouped radio inputs are mutually exclusive -->
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Plain" /> Plain</label>
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Whole wheat" /> Whole wheat</label>
<label><input type="radio" bind:group={let tortilla: stringtortilla} value="Spinach" /> Spinach</label>
<!-- grouped checkbox inputs populate an array -->
<label><input type="checkbox" bind:group={let fillings: never[]fillings} value="Rice" /> Rice</label>
<label><input type="checkbox" bind:group={let fillings: never[]fillings} value="Beans" /> Beans</label>
<label><input type="checkbox" bind:group={let fillings: never[]fillings} value="Cheese" /> Cheese</label>
<label><input type="checkbox" bind:group={let fillings: never[]fillings} value="Guac (extra)" /> Guac (extra)</label>
<p>Tortilla: {let tortilla: stringtortilla}</p>
<p>Fillings: {let fillings: never[]fillings.Array<never>.join(separator?: string): stringAdds all the elements of an array into a string, separated by the specified separator string.
join(', ') || 'None'}</p>
<style>
label {
display: block;
}
</style>
bind:grouponly works if the inputs are in the same Svelte component.
<input bind:files>
On <input> elements with type="file", you can use bind:files to get the FileList of selected files. When you want to update the files programmatically, you always need to use a FileList object. Currently FileList objects cannot be constructed directly, so you need to create a new DataTransfer object and get files from there.
<script lang="ts">
let files = $state();
function clear() {
files = new DataTransfer().files; // null or undefined does not work
}
</script>
<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>clear</button><script>
let files = $state();
function clear() {
files = new DataTransfer().files; // null or undefined does not work
}
</script>
<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>clear</button>FileList objects also cannot be modified, so if you want to e.g. delete a single file from the list, you need to create a new DataTransfer object and add the files you want to keep.
DataTransfermay not be available in server-side JS runtimes. Leaving the state that is bound tofilesuninitialized prevents potential errors if components are server-side rendered.
<select bind:value>
A <select> value binding corresponds to the value property on the selected <option>, which can be any value (not just strings, as is normally the case in the DOM).
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b}>b</option>
<option value={c}>c</option>
</select>A <select multiple> element behaves similarly to a checkbox group. The bound variable is an array with an entry corresponding to the value property of each selected <option>.
<select multiple bind:value={fillings}>
<option value="Rice">Rice</option>
<option value="Beans">Beans</option>
<option value="Cheese">Cheese</option>
<option value="Guac (extra)">Guac (extra)</option>
</select>When the value of an <option> matches its text content, the attribute can be omitted.
<select multiple bind:value={fillings}>
<option>Rice</option>
<option>Beans</option>
<option>Cheese</option>
<option>Guac (extra)</option>
</select>You can give the <select> a default value by adding a selected attribute to the <option> (or options, in the case of <select multiple>) that should be initially selected. If the <select> is part of a form, it will revert to that selection when the form is reset. Note that for the initial render the value of the binding takes precedence if it’s not undefined.
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b} selected>b</option>
<option value={c}>c</option>
</select><audio>
<audio> elements have their own set of bindings — five two-way ones…
…and six readonly ones:
<audio src={clip} bind:duration bind:currentTime bind:paused></audio><video>
<video> elements have all the same bindings as <audio> elements, plus readonly videoWidth and videoHeight bindings.
<img>
<img> elements have two readonly bindings:
<details bind:open>
<details> elements support binding to the open property.
<details bind:open={isOpen}>
<summary>How do you comfort a JavaScript bug?</summary>
<p>You console it.</p>
</details>window and document
To bind to properties of window and document, see <svelte:window> and <svelte:document>.
Contenteditable bindings
Elements with the contenteditable attribute support the following bindings:
There are subtle differences between
innerTextandtextContent.
<div contenteditable="true" bind:innerHTML={html}></div>Dimensions
All visible elements have the following readonly bindings, measured with a ResizeObserver:
clientWidthclientHeightoffsetWidthoffsetHeightcontentRectcontentBoxSizeborderBoxSizedevicePixelContentBoxSize
<div bind:offsetWidth={width} bind:offsetHeight={height}>
<Chart {width} {height} />
</div>
display: inlineelements do not have a width or height (except for elements with ‘intrinsic’ dimensions, like<img>and<canvas>), and cannot be observed with aResizeObserver. You will need to change thedisplaystyle of these elements to something else, such asinline-block. Note that CSS transformations do not triggerResizeObservercallbacks.
bind:this
bind:this={dom_node}To get a reference to a DOM node, use bind:this. The value will be undefined until the component is mounted — in other words, you should read it inside an effect or an event handler, but not during component initialisation:
<script lang="ts">
let canvas: HTMLCanvasElement;
$effect(() => {
const ctx = canvas.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvas}></canvas><script>
/** @type {HTMLCanvasElement} */
let canvas;
$effect(() => {
const ctx = canvas.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvas}></canvas>Components also support bind:this, allowing you to interact with component instances programmatically.
<ShoppingCart bind:this={cart} />
<button onclick={() => cart.empty()}> Empty shopping cart </button><script lang="ts">
// All instance exports are available on the instance object
export function function (local function) empty(): voidempty() {
// ...
}
</script><script>
// All instance exports are available on the instance object
export function function (local function) empty(): voidempty() {
// ...
}
</script>In case of using the function bindings, the getter is required to ensure that the correct value is nullified on component or element destruction.
bind:property for components
bind:property={variable}You can bind to component props using the same syntax as for elements.
<Keypad bind:value={pin} />While Svelte props are reactive without binding, that reactivity only flows downward into the component by default. Using bind:property allows changes to the property from within the component to flow back up out of the component.
To mark a property as bindable, use the $bindable rune:
<script lang="ts">
let { let readonlyProperty: anyreadonlyProperty, let bindableProperty: anybindableProperty = function $bindable<unknown>(fallback?: unknown): unknown
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
$function $bindable<unknown>(fallback?: unknown): unknown
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
bindable() } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
props();
</script><script>
let { let readonlyProperty: anyreadonlyProperty, let bindableProperty: anybindableProperty = function $bindable<unknown>(fallback?: unknown): unknown
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
$function $bindable<unknown>(fallback?: unknown): unknown
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
bindable() } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
props();
</script>Declaring a property as bindable means it can be used using bind:, not that it must be used using bind:.
Bindable properties can have a fallback value:
<script lang="ts">
let { let bindableProperty: anybindableProperty = function $bindable<"fallback value">(fallback?: "fallback value" | undefined): "fallback value"
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
$function $bindable<"fallback value">(fallback?: "fallback value" | undefined): "fallback value"
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
bindable('fallback value') } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
props();
</script><script>
let { let bindableProperty: anybindableProperty = function $bindable<"fallback value">(fallback?: "fallback value" | undefined): "fallback value"
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
$function $bindable<"fallback value">(fallback?: "fallback value" | undefined): "fallback value"
namespace $bindable
Declares a prop as bindable, meaning the parent component can use bind:propName={value} to bind to it.
let { propName = $bindable() }: { propName: boolean } = $props();
bindable('fallback value') } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
props();
</script>This fallback value only applies when the property is not bound. When the property is bound and a fallback value is present, the parent is expected to provide a value other than undefined, else a runtime error is thrown. This prevents hard-to-reason-about situations where it’s unclear which value should apply.