Svelte.js 3 Input Binding Tutorial

In this tutorial we learn how to react to events and output data at the same time with two-way databinding in Svelte.

We cover databinding to most form elements, as well as basic form handling.

Lesson Video

If you prefer to learn visually, you can watch this lesson in video format.

Lesson Project

If you want to follow along with the examples in this lesson, you’ll need a Svelte app that was cloned with degit or scaffolded with Vite

If you already have an app from previous lessons, you can use that instead.

Input binding in Svelte with the 'bind' directive

Two-way databinding combines string interpolation and event binding to react to events and output data at the same time. This ensures that the Logic and the View is always in sync.

Two-way databinding in Svelte uses the bind directive on the attribute of the element we want to take input from, like a text field. Its value references the data from the Logic that we want to modify.

Syntax: bind
<element bind:attribute={data} />

As an example, let’s create a name variable and then bind it to the text field’s value attribute. Finally, to help the demonstration, we’ll output the name in the text field’s label.

Example: src/App.svelte
<script>
  let firstName = ''
</script>

<label for="name">Name: {firstName}</label>
<input type="text" id="name" bind:value={firstName}>

If we go to the browser and type a name in the text field, it will automatically update in the label.

If you remember from the lesson on event handling , we had to do the same thing in a two step process where we used a function to modify the data property.

Example: src/App.svelte
<script>
  let name = ''

  function getInput(event) {
    // get the value of the input on the
    // event object and assign it to 'name'
    name = event.target.value
  }
</script>

<p>Your name: { name }</p>
<input type="text" on:input={getInput}>

With the bind directive, the data is directly connected to the input so we don’t need the function.

Input binding form elements in Svelte

Because forms are such a common part of an application, it’s worth it to quickly go over how to bind them with the bind directive.

Input binding with a Textarea in Svelte

Binding data from a textarea input element is exactly the same as with a text field.

Example: src/App.svelte
<script>
  let synopsis = ''
</script>

<label for="desc">Film Synopsis: {synopsis}</label>
<textarea id="desc" bind:value={synopsis} />

Anything we type in the textarea will be shown in the label.

Input binding with a Single-Select Dropdown in Svelte

When we use a grouped element, we specify the bind directive on the parent.

Single-select dropdown elements use select as the parent and option as the children.

Example: src/App.svelte
<script>
  let size = ''
</script>

<label for="dropdown">Shirt size: {size}</label>
<select id="dropdown" bind:value={size}>
  <option value="">Please select your size</option>
  <option value="sm">Small</option>
  <option value="md">Medium</option>
  <option value="lg">Large</option>
</select>

When we choose an option in the dropdown, it’s value will display in the paragraph.

note We chose to have the first option’s value empty. This allows us to create logic to check if the user has actively chosen an option, which can be useful when a dropdown is a mandatory option on a form.

Input binding with a Multi-Select Control in Svelte

When we use a multi-select control, the data must be stored in a multi-value data container, like an array.

A multi-select control uses select as the parent and option as the children, but adds the multiple attribute to allow more than one selection.

tip To keep this example simple, we use the vanilla Javascript join method to display the items nicely. Typically this would be done with Svelte’s built-in iteration rendering directive.

Example: src/App.svelte
<script>
  let visited = []
</script>

<label for="dropdown">Countries visited: { visited.join(', ') }</label>
<select id="dropdown" bind:value={visited} multiple>
  <option value="US">United States</option>
  <option value="UK">United Kingdom</option>
  <option value="AU">Australia</option>
  <option value="NZ">New Zealand</option>
</select>

When we Ctrl + Click elements in the multi-select control, it will display those elements in the label.

note Only items that have been checked will be added to the array, there is no “unchecked” value to store.

Input binding with a Radio Button Group in Svelte

When working with radio buttons, we need to bind to each individual radio button.

Only one radio button from a group can be selected, so we need bind to the group instead of the value .

Example: src/App.svelte
<script>
  let rating = ''
</script>

<p>Rate this page: {rating}</p>
<label>
  <input type="radio" value="Bad" bind:group={rating} />
  Bad
</label>
<label>
  <input type="radio" value="Okay" bind:group={rating} />
  Okay
</label>
<label>
  <input type="radio" value="Good" bind:group={rating} />
  Good
</label>

When we select one of the radio buttons on the page, it will display the corresponding value.

Input binding with a Checkbox in Svelte

A single checkbox without a value attribute will return a boolean true or false. So, when working with a single checkbox, we bind to the checked attribute instead of the value .

Example: src/App.svelte
<script>
  let subscribe = false
</script>

<label>
  <input type="checkbox" bind:checked={subscribe} />
  Would you like subscribe to our newsletter? ({ subscribe })
</label>

When we check and uncheck the checkbox above, it will display true or false.

If we want the checkbox to be checked by default, we simply change the variable to be true.

Example: src/App.svelte
<script>
  let subscribe = true
</script>

<label>
  <input type="checkbox" bind:checked={subscribe} />
  Would you like subscribe to our newsletter? ({ subscribe })
</label>

This time, the checkbox will be checked when the page loads.

Input binding with a Checkbox Group in Svelte

Checkbox groups work the same as radio groups. We need to bind to the group instead of the value on each checkbox element.

As an example, let’s simulate a shopping list that has been populated with some shopping items. The user can then check items as they collect them in their cart.

tip To keep this example simple, we use the vanilla Javascript join method to display the items nicely. Typically this would be done with Svelte’s built-in iteration rendering directive.

Example: src/App.svelte
<script>
  let shoppingList = []
</script>

<p>Items in cart: { shoppingList.join(', ') }</p>
<label>
  <input type="checkbox" value="Bread" bind:group={shoppingList} />
  Bread
</label>
<label>
  <input type="checkbox" value="Milk" bind:group={shoppingList} />
  Milk
</label>
<label>
  <input type="checkbox" value="Eggs" bind:group={shoppingList} />
  Eggs
</label>

note Only items that have been checked will be added to the array, there is no “unchecked” value to store.

Basic form handling in Svelte

Now that we understand how to work with various form controls, let’s quickly discuss how to submit the data.

All we need to do is add a submit event to our form that references an event handler function. The function is responsible for performing any operations on the data, like validating it and/or sending it to a storage layer.

To keep the example simple, our handler function will just display an alert. Typically, form data would be sent to a storage layer like Firebase.

Example: src/App.svelte
<script>
  let firstName = ''

  function processForm() {
    alert(`Your name is ${firstName}`)
  }
</script>

<form on:submit={processForm}>
  <label for="name">Name: {firstName}</label>
  <input type="text" id="name" bind:value={firstName}>

  <button>Submit</button>
</form>

When we submit the form, it will display an alert popup with the name we entered.