0
0
SvelteHow-ToBeginner · 3 min read

How to Create a Search Filter in Svelte Easily

In Svelte, create a search filter by binding an <input> element to a variable and then use that variable to filter your list with JavaScript's filter() method. The filtered list updates reactively as the user types, showing only matching items.
📐

Syntax

Use bind:value on an <input> to link it to a variable. Then filter your array using that variable inside a reactive statement or directly in the template.

This keeps the UI and data in sync automatically.

svelte
<script>
  let search = '';
  let items = ['Apple', 'Banana', 'Cherry', 'Date'];
  $: filteredItems = items.filter(item =>
    item.toLowerCase().includes(search.toLowerCase())
  );
</script>

<input type="text" placeholder="Search..." bind:value={search} />
<ul>
  {#each filteredItems as item}
    <li>{item}</li>
  {/each}
</ul>
Output
An input box labeled 'Search...' and a list below that updates to show only items containing the typed text.
💻

Example

This example shows a list of fruits filtered by the search input. Typing filters the list in real time.

svelte
<script>
  let search = '';
  let fruits = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'];
  $: filteredFruits = fruits.filter(fruit =>
    fruit.toLowerCase().includes(search.toLowerCase())
  );
</script>

<input type="text" placeholder="Search fruits..." bind:value={search} aria-label="Search fruits" />
<ul>
  {#each filteredFruits as fruit}
    <li>{fruit}</li>
  {/each}
</ul>
Output
An input field with placeholder 'Search fruits...' and a list below that updates to show fruits matching the typed text.
⚠️

Common Pitfalls

  • Not using bind:value on the input causes the variable not to update.
  • Filtering without normalizing case can cause missed matches.
  • Filtering the original array directly in the template without a reactive statement can hurt performance.
svelte
<script>
  let search = '';
  let items = ['Apple', 'Banana', 'Cherry'];
  // Wrong: no reactive statement, filtering inside template
</script>

<input type="text" bind:value={search} />
<ul>
  {#each items.filter(item => item.toLowerCase().includes(search.toLowerCase())) as item}
    <li>{item}</li>
  {/each}
</ul>

<!-- Right way: use reactive statement with case normalization -->
<script>
  $: filteredItems = items.filter(item =>
    item.toLowerCase().includes(search.toLowerCase())
  );
</script>
Output
Input box and list that may not filter correctly if case is mismatched or performance issues if filtering done inside template.
📊

Quick Reference

  • bind:value: Connect input value to a variable.
  • Reactive statement ($:): Automatically update filtered list when search changes.
  • Array.filter(): Filter items based on search text.
  • toLowerCase(): Normalize case for matching.

Key Takeaways

Use bind:value on inputs to keep search text reactive.
Filter your list with Array.filter() and normalize case for better matching.
Use Svelte's reactive statements ($:) to update filtered results automatically.
Avoid filtering directly inside the template for better performance and clarity.
Add aria-label to inputs for accessibility.