Svelte bindings are useful to connect your UI with your component state. As this is a widespread pattern for frameworks, Svelte provides some directives for you.
Tldr;
I spend some time to write down everything about bindings. I show you how you can use them in Svelte to connect your logic with your UI.
If you like this article, please share it, follow me, check out my RSS feed and subscribe to my newsletter.
Table of Contents
- Text Inputs and Numeric Inputs
- Checkbox, Radio and Group Inputs
- Textareas and Select
- Contenteditable Elements
- Each block bindings
- Media Elements Each block bindings
- Dimensions, This and Component bindings
- Next steps
1. Text Inputs and Numeric Inputs
Text inputs are one of the most common use cases for us developers, where we need to sync data between the view layer and our component state. You can archive this by adding the bind:value
to your input HTML tag.
<script>
let variableName = 'Nora';
</script>
<input bind:value="{variableName}" />
<h2>Whazzzz uuup {variableName}</h2>
You tell the compiler that you want to have a two-way data binding between your component variable variableName
and the input value. As simple as the bind
directive works for strings in text inputs, you can use it for numeric values like inputs type="number"
and type="range"
.
<script>
let counter = 1;
</script>
<input type="number" bind:value="{counter}" min="0" max="10" />
<input type="range" bind:value="{counter}" min="0" max="10" />
2. Checkbox, Radio and Group Inputs
Checkboxes are used in nearly every form. If you want to bind your checkbox to a component variable, you can add the bind:checked
directive.
<script>
let showMeMyAwesomeGif = false;
</script>
<label>
<input type="checkbox" bind:checked="{showMeMyAwesomeGif}" />
Yes, show me my GIF
</label>
{#if showMeMyAwesomeGif}
<iframe
src="https://giphy.com/embed/Z6f7vzq3iP6Mw"
width="480"
height="203"
frameborder="0"
class="giphy-embed"
allowfullscreen
></iframe>
<p>
<a href="https://giphy.com/gifs/awesome-yes-old-school-Z6f7vzq3iP6Mw"
>via GIPHY</a
>
</p>
{:else}
<p>Nooooo awesome GIF here</p>
{/if}
Sometimes you need your users to fill out the form with multiple inputs for the same values. For these cases, you can group your inputs. Radio input in the same group are mutually exclusive, and checkbox values form an array of the selected values. To group inputs, you add the bind:group
directive onto the input tags.
<script>
let scoops = 1;
let flavours = ['Mint choc chip'];
let menu = ['Cookies and cream', 'Mint choc chip', 'Raspberry ripple'];
function join(flavours) {
if (flavours.length === 1) return flavours[0];
return `${flavours.slice(0, -1).join(', ')} and ${
flavours[flavours.length - 1]
}`;
}
</script>
<h2>Size</h2>
<label>
<input type="radio" bind:group="{scoops}" value="{1}" />
One scoop
</label>
<label>
<input type="radio" bind:group="{scoops}" value="{2}" />
Two scoops
</label>
<label>
<input type="radio" bind:group="{scoops}" value="{3}" />
Three scoops
</label>
<h2>Flavours</h2>
{#each menu as flavour}
<label>
<input type="checkbox" bind:group="{flavours}" value="{flavour}" />
{flavour}
</label>
{/each} {#if flavours.length === 0}
<p>Please select at least one flavour</p>
{:else if flavours.length > scoops}
<p>Can't order more flavours than scoops!</p>
{:else}
<p>
You ordered {scoops} {scoops === 1 ? 'scoop' : 'scoops'} of {join(flavours)}
</p>
{/if}
3. Textareas and Select
You can connect the textarea
tag from the view to your component similar to the input text element with the bind:value
directive.
<script>
let value = `Checkout your textarea value with two-way data binding`;
</script>
<style>
textarea {
width: 100%;
height: 200px;
}
</style>
<textarea bind:value />
{@html value}
Select values are bind like input text and textarea. You add the bind:value
directive. Additionally, you can select multiple values with the multiple
attribute.
<script>
let scoops = 1;
let happyness = ['Happy'];
let valuesOfHappyness = ['Happy', 'Curious', 'Excited'];
function join(happyness) {
if (happyness.length === 1) return happyness[0];
return `${happyness.slice(0, -1).join(', ')} and ${
happyness[flavours.length - 1]
}`;
}
</script>
<h2>Happyness</h2>
<select multiple bind:value="{happyness}">
{#each valuesOfHappyness as flavour}
<option value="{flavour}">{flavour}</option>
{/each}
</select>
{#if happyness.length === 0}
<p>Please select at least one value</p>
{:else}
<p>You selected {join(happyness)}</p>
{/if}
4. Contenteditable Elements
If you have a contenteditable element you can use the bind directive as well to bind the innerHTML or the text content of the element. Check out my example below:
<script>
let html = '<p>Hello World</p>';
</script>
<div contenteditable="true" bind:innerHTML="{html}"></div>
<pre>{html}</pre>
<style>
[contenteditable] {
padding: 0.5em;
border: 1px solid #eee;
border-radius: 4px;
}
</style>
5. Each block bindings
In some cases, you need to bind values inside a loop. With Svelte, you can do this by adding the directives to your elements you want to connect to your component. You only have to take care if you're going to work with immutable data. Check out the hint from svelte.dev
Note that interacting with these
<input>
elements will mutate the array. If you prefer to work with immutable data, you should avoid these bindings and use event handlers instead.
<script>
let todos = [
{ done: false, text: 'Olives' },
{ done: false, text: 'Goat cheese' },
{ done: false, text: 'Wine' },
];
</script>
<h1>Todos</h1>
{#each todos as todo}
<div class:done="{todo.done}">
<input type="checkbox" bind:checked="{todo.done}" />
<input placeholder="What needs to be done?" bind:value="{todo.text}" />
</div>
{/each} {JSON.stringify(todos)}
6. Media Elements Each block bindings
You recognize already that it is quite simple to add bindings to your elements. Video and audio elements are a little more complex as you can bind multiple properties. Some of the properties are read-only, and others are two-way bindings. Check out the list below from the official tutorial page:
Video and audio
Read Only
- duration (read-only) — the total duration of the video, in seconds
- buffered (read-only) — an array of {start, end} objects
- seekable (read-only) — ditto
- played (read-only) — ditto
- seeking (read-only) — boolean
- ended (read-only) — boolean
- videoWidth (read-only) — ONLY video
- videoHeight (read-only) — ONLY video
Two-way
- currentTime — the current point in the video, in seconds
- playbackRate — how fast to play the video, where 1 is 'normal'
- paused — this one should be self-explanatory
- volume — a value between 0 and 1
- muted — a boolean value where true is muted
You find an excellent example of video bindings in the official tutorial.
7. Dimensions, This and Component bindings
Dimensions
In Svelte every block-level element has clientWidth
, clientHeight
, offsetWidth
and offsetHeight
bindings. These bindings are read-only.
What you could do is to apply a component state variable to an inline style attribute. This way, you can change the width and height of an element.
BUT please keep the web performance in mind! Changing some style attribute might force the browser to reflow your page.
<script>
let color = 'green';
</script>
<style>
input {
display: block;
}
div {
display: inline-block;
}
span {
word-break: break-all;
}
</style>
<input type="text" bind:value="{color}" />
<div bind:clientWidth="{w}" bind:clientHeight="{h}">
<span style="color: {color}px">Let's change my color</span>
</div>
This Binding
The read-only this
binding applies to every element (and component) you get a reference to the component after the component is mounted.
Component Binding
As you can use the binding directive to DOM elements, you can use them as well on custom components. The Svelte tutorial gives you a hint at this to use them sparingly because it can be hard to track the data flow.
8. Next steps
You find all the resources for this article on GitHub. Feel free to check it out, try some stuff or fork it.
You should now be well packed for your first component. If you want to dive deeper, I recommend taking an hour or two of your time and going through the official Svelte training tutorial. 👨🏫
If you like this article, smile for a moment, share it, follow me, check out my RSS feed and subscribe to my newsletter.
Cheers Marc
Top comments (0)