erb javascript 23 lines · 2 tabs

Filter UI that syncs query params via Stimulus (no front-end router)

Henry Kim Jan 2026
2 tabs
<form data-controller="query-sync" data-action="change->query-sync#apply">
  <select name="status" class="rounded border p-2">
    <option value="">Any</option>
    <option value="open">Open</option>
    <option value="closed">Closed</option>
  </select>
</form>
2 files · erb, javascript Explain with highlit

Filters are better when the URL reflects state. I use a small Stimulus controller that updates the query string as filters change, then triggers a Turbo visit (often with data-turbo-action='replace'). This gives shareable URLs and correct back-button behavior without pulling in a router. The server remains the source of truth for filtering logic, and the UI can still degrade to a normal GET form. The controller’s job is just to serialize inputs and update the URL; it doesn’t own filtering. This is also useful for multi-select filters and sorting. I keep it conservative: debounce changes, and don’t trigger visits if the query string didn’t actually change.


Related snips

Share this code

Here's the card — post it anywhere.

Filter UI that syncs query params via Stimulus (no front-end router) — share card
Link copied