Svelte and SvelteKit course · Module 5: Bindings

Bifrost - Data Bindings

2 min read ·
In this lesson4

Welcome to Bifrost - the rainbow bridge connecting the worlds! Bindings in Svelte connect data to DOM elements just as Bifrost connects Asgard to Midgard - bidirectionally!

What are Bindings?

Bindings create two-way synchronization between a variable and a DOM element:

<script>
  let vikingName = $state('');
</script>

<!-- Two-way binding -->
<input bind:value={vikingName} />

<!-- vikingName updates as you type -->
<p>Welcome, {vikingName}!</p>

bind:value - Text Fields

<script>
  let name = $state('');
  let message = $state('');
  let age = $state(18);
</script>

<!-- Text input -->
<input type="text" bind:value={name} />

<!-- Textarea -->
<textarea bind:value={message}></textarea>

<!-- Numeric input -->
<input type="number" bind:value={age} />

bind:checked - Checkboxes

<script>
  let isWarrior = $state(true);
  let hasShield = $state(false);
</script>

<label>
  <input type="checkbox" bind:checked={isWarrior} />
  Warrior
</label>

<label>
  <input type="checkbox" bind:checked={hasShield} />
  Has shield
</label>

<p>Status: {isWarrior ? 'Warrior' : 'Civilian'} {hasShield ? 'with shield' : ''}</p>

bind:group - Radio and Checkbox Groups

<script>
  // Radio - single value
  let selectedWeapon = $state('sword');

  // Checkbox group - array of values
  let skills = $state([]);
</script>

<h3>Choose weapon:</h3>
<label><input type="radio" bind:group={selectedWeapon} value="sword" /> Sword</label>
<label><input type="radio" bind:group={selectedWeapon} value="axe" /> Axe</label>
<label><input type="radio" bind:group={selectedWeapon} value="spear" /> Spear</label>

<h3>Choose skills:</h3>
<label><input type="checkbox" bind:group={skills} value="sailing" /> Sailing</label>
<label><input type="checkbox" bind:group={skills} value="fighting" /> Fighting</label>
<label><input type="checkbox" bind:group={skills} value="trading" /> Trading</label>

<p>Weapon: {selectedWeapon}</p>
<p>Skills: {skills.join(', ')}</p>

Bifrost connects worlds - bindings connect data to the interface!

Code for this lesson: App.svelte
<script>
  // Bifröst - Bridge between data and view
  // bind: - two-way binding

  let name = $state('');
  let age = $state(25);
  let isWarrior = $state(false);
  let clan = $state('vikings');
</script>

<main class="bifrost">
  <h1>Bifröst - Bindings</h1>
  <p class="subtitle">Bridge between data and view</p>

  <section>
    <h2>Text Input (bind:value)</h2>
    <input type="text" bind:value={name} placeholder="Warrior name" />
    <p>Hello, <strong>{name || 'stranger'}</strong>!</p>
  </section>

  <section>
    <h2>Number Input</h2>
    <input type="number" bind:value={age} min="18" max="100" />
    <p>Age: {age} years</p>
    <input type="range" bind:value={age} min="18" max="100" />
  </section>

  <section>
    <h2>Checkbox (bind:checked)</h2>
    <label>
      <input type="checkbox" bind:checked={isWarrior} />
      I am a warrior
    </label>
    <p>{isWarrior ? 'Ready for battle!' : 'Staying home'}</p>
  </section>

  <section>
    <h2>Select</h2>
    <select bind:value={clan}>
      <option value="vikings">Vikings</option>
      <option value="saxons">Saxons</option>
      <option value="danes">Danes</option>
    </select>
    <p>Clan: <strong>{clan}</strong></p>
  </section>

  <div class="summary">
    <h2>Summary</h2>
    <p>Name: {name || '-'}</p>
    <p>Age: {age}</p>
    <p>Warrior: {isWarrior ? 'Yes' : 'No'}</p>
    <p>Clan: {clan}</p>
  </div>
</main>

<style>
  .bifrost {
    font-family: 'Georgia', serif;
    max-width: 600px;
    margin: 0 auto;
    padding: 2rem;
    background: linear-gradient(135deg, #1a0a2e 0%, #2d1b4e 100%);
    color: #e8d5f7;
    min-height: 100vh;
  }

  h1 {
    color: #ffd700;
    text-align: center;
  }

  .subtitle {
    text-align: center;
    color: #b19cd9;
  }

  section {
    background: rgba(177, 156, 217, 0.1);
    border: 1px solid #b19cd9;
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
  }

  h2 {
    color: #b19cd9;
    font-size: 1rem;
    margin-top: 0;
  }

  input[type="text"],
  input[type="number"],
  select {
    width: 100%;
    padding: 0.5rem;
    background: rgba(0,0,0,0.3);
    border: 1px solid #b19cd9;
    border-radius: 4px;
    color: #e8d5f7;
    margin-bottom: 0.5rem;
  }

  input[type="range"] {
    width: 100%;
  }

  label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
  }

  strong {
    color: #ffd700;
  }

  .summary {
    background: rgba(255, 215, 0, 0.1);
    border: 2px solid #ffd700;
    border-radius: 8px;
    padding: 1rem;
    margin-top: 1rem;
  }

  .summary h2 {
    color: #ffd700;
  }
</style>

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What does bind:value do in Svelte?

Hands-on tasks in the game

  • Code editor

    Complete the code so the input is bound to the name variable

Useful articles