Skip to main content
Svelte Fundamentals
CHAPTER 11 Beginner

Forms and User Input

Updated: May 18, 2026
5 min read

# CHAPTER 11

Forms and User Input

1. Chapter Introduction

Forms are the primary way users send data to your application. Svelte's bind: directive makes form handling dramatically simpler than React's controlled components — you bind a variable to an input, and Svelte keeps them synchronized automatically. No onChange handlers, no setState calls.

2. Learning Objectives

  • Use bind:value for text, number, and textarea inputs.
  • Use bind:checked for checkboxes.
  • Use bind:group for radio buttons and multi-select checkboxes.
  • Implement form validation and display error messages.
  • Handle form submission with on:submit|preventDefault.

3. Text and Number Inputs

svelte
12345678910111213
<script>
  let name = &#039;';
  let email = &#039;';
  let age = 18;
  let bio = &#039;';
</script>

<input bind:value={name} placeholder="Full Name" />
<input bind:value={email} type="email" placeholder="Email" />
<input bind:value={age} type="number" min="0" max="120" />
<textarea bind:value={bio} placeholder="Tell us about yourself..."></textarea>

<p>Hello, {name || &#039;stranger'}! You are {age} years old.</p>

4. Checkboxes and Radio Buttons

svelte
12345678910111213141516171819202122232425262728293031323334353637
<script>
  let acceptTerms = false;
  let subscribeNewsletter = true;
  let paymentMethod = &#039;card';
  let selectedHobbies = [];
  let hobbies = [&#039;Reading', 'Coding', 'Gaming', 'Cooking'];
</script>

<!-- Checkbox -->
<label>
  <input type="checkbox" bind:checked={acceptTerms} />
  I accept the Terms & Conditions
</label>

<!-- Radio buttons with bind:group -->
<fieldset>
  <legend>Payment Method</legend>
  {#each ['card', 'paypal', 'crypto'] as method}
    <label>
      <input type="radio" bind:group={paymentMethod} value={method} />
      {method.charAt(0).toUpperCase() + method.slice(1)}
    </label>
  {/each}
</fieldset>
<p>Selected: {paymentMethod}</p>

<!-- Multiple checkboxes with bind:group -->
<fieldset>
  <legend>Hobbies</legend>
  {#each hobbies as hobby}
    <label>
      <input type="checkbox" bind:group={selectedHobbies} value={hobby} />
      {hobby}
    </label>
  {/each}
</fieldset>
<p>Selected: {selectedHobbies.join(&#039;, ')}</p>

5. Select Dropdowns

svelte
123456789101112131415161718192021
<script>
  let country = &#039;';
  let countries = [&#039;USA', 'UK', 'Canada', 'Australia', 'India'];
  let selectedSkills = [];
  let skills = [&#039;HTML', 'CSS', 'JavaScript', 'Svelte', 'Node.js'];
</script>

<!-- Single select -->
<select bind:value={country}>
  <option value="">-- Choose a country --</option>
  {#each countries as c}
    <option value={c}>{c}</option>
  {/each}
</select>

<!-- Multiple select -->
<select bind:value={selectedSkills} multiple>
  {#each skills as skill}
    <option value={skill}>{skill}</option>
  {/each}
</select>

6. Form Validation and Submission

svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
<script>
  let form = { name: &#039;', email: '', password: '', confirmPassword: '' };
  let errors = {};
  let submitted = false;

  function validate() {
    errors = {};
    if (!form.name.trim()) errors.name = &#039;Name is required';
    else if (form.name.length < 2) errors.name = &#039;Name must be at least 2 characters';
    if (!form.email.includes(&#039;@')) errors.email = 'Enter a valid email';
    if (form.password.length < 6) errors.password = &#039;Password must be at least 6 characters';
    if (form.password !== form.confirmPassword) errors.confirmPassword = &#039;Passwords do not match';
    return Object.keys(errors).length === 0;
  }

  function handleSubmit() {
    if (validate()) {
      submitted = true;
      console.log(&#039;Form submitted:', form);
    }
  }
</script>

{#if submitted}
  <div class="success">✅ Registration successful!</div>
{:else}
  <form on:submit|preventDefault={handleSubmit}>
    <div class="field">
      <label>Full Name</label>
      <input bind:value={form.name} class:error={errors.name} placeholder="Your name" />
      {#if errors.name}<span class="error-msg">{errors.name}</span>{/if}
    </div>

    <div class="field">
      <label>Email</label>
      <input bind:value={form.email} type="email" class:error={errors.email} />
      {#if errors.email}<span class="error-msg">{errors.email}</span>{/if}
    </div>

    <div class="field">
      <label>Password</label>
      <input bind:value={form.password} type="password" class:error={errors.password} />
      {#if errors.password}<span class="error-msg">{errors.password}</span>{/if}
    </div>

    <div class="field">
      <label>Confirm Password</label>
      <input bind:value={form.confirmPassword} type="password" class:error={errors.confirmPassword} />
      {#if errors.confirmPassword}<span class="error-msg">{errors.confirmPassword}</span>{/if}
    </div>

    <button type="submit">Register</button>
  </form>
{/if}

7. Common Mistakes

  • Using on:input instead of bind:value: Both work, but bind:value is cleaner and Svelte-idiomatic.
  • Forgetting |preventDefault on form submit: Without it, the form causes a page reload.

8. MCQs

Question 1

What directive creates two-way binding for an input's value?

Question 2

What directive binds a checkbox's checked state?

Question 3

What directive groups radio buttons and multi-checkboxes?

Question 4

What modifier prevents form page reload on submit?

Question 5

For a number input, does bind:value return a string or number?

Question 6

How do you bind a textarea?

Question 7

For a multi-select, what does bind:value give you?

Question 8

What class directive adds an error class conditionally?

Question 9

How do you reset a form's state to empty values?

Question 10

When should you validate — on submit only or on each field change?

9. Interview Questions

  • Q: Compare Svelte's bind:value approach to React's controlled components. What is simpler?
  • Q: How would you implement real-time password strength validation in Svelte?

10. Summary

Svelte's form handling is the most concise of any framework. bind:value, bind:checked, and bind:group replace verbose controlled component patterns. Combined with |preventDefault and reactive validation using $:, Svelte forms are both simple to write and powerful.

11. Next Chapter Recommendation

In Chapter 12: Lifecycle Functions in Svelte, we learn when to run code during a component's creation, updates, and destruction — essential for data fetching, timers, and cleanup.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·