Svelte bind directive - A cheatsheet
Tags: svelte, webdev, javascript
Published: 2020-07-20 15:28:40

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](https://marcradziwill.com/blog/rss.xml) and [subscribe to my newsletter](https://marcradziwill.com/newsletter/).

---

## Table of Contents

1. [Text Inputs and Numeric Inputs](#text)
2. [Checkbox, Radio and Group Inputs](#check)
3. [Textareas and Select](#textareas)
4. [Contenteditable Elements](#contenteditable)
5. [Each block bindings](#block)
6. [Media Elements Each block bindings](#media)
7. [Dimensions, This and Component bindings](#dimen)
8. [Next steps](#next)

<hr />

## 1. Text Inputs and Numeric Inputs <div id="text"></div>

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.

```html
<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"`.

```html
<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 <div id="check"></div>

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.

```html
<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.

```html
<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}
```

[![Web Performance Checklist](https://dev-to-uploads.s3.amazonaws.com/i/i9nrcwt53letp80a28eg.png)](https://devcademy.marcradziwill.com/web-performance-checklist/)


## 3. Textareas and Select <div id="textarea"></div>

You can connect the `textarea` tag from the view to your component similar to the input text element with the `bind:value` directive.

```html
<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.

```html
<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 <div id="contenteditable"></div>

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:

```html
<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 <div id="block"></div>

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.

```html
<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 <div id="media"></div>

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 <div id="av"></div>

#### 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](https://svelte.dev/tutorial/media-elements).

## 7. Dimensions, This and Component bindings <div id="dimen"></div>

### 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.

```html
<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 <div id="next"></div>

You find all the resources for this article on [GitHub](https://github.com/marcradziwill/svelte-bindings-tutorial). 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](https://marcradziwill.com/blog/rss.xml) and [subscribe to my newsletter](https://marcradziwill.com/newsletter/).

Cheers Marc