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:valueon 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.