Triggers, forms, and feedback
Use trigger modifiers
Debounce input, suppress duplicate values, limit frequency, filter events, or allow a trigger only once.
Search-as-you-type is the textbook case for trigger modifiers. Without them, every keyup fires a request:
<input type="search" name="q"
hx-get="/search"
hx-trigger="keyup changed delay:500ms, search"
hx-target="#results"
hx-sync="this:replace">
changed suppresses requests when the value is identical to the last one sent. delay:500ms debounces: each new keyup resets the timer, so typing “tasks” sends one request after you pause, not five.
The search event also handles clearing the native search field with the × button.
Debouncing does not cancel a request already in flight. hx-sync="this:replace" aborts the older search when a newer one starts. That stops a slow old response from overwriting fresh results. I see that bug often on fast typists with slow servers.
Other modifiers solve different problems:
throttle:500msallows at most one request per intervalonceaccepts only the first matching eventfrom:bodylistens on another elementtarget:<selector>filters events by their original targetqueue:first,queue:last, orqueue:allcontrols events arriving during a request
Use the smallest set that expresses a real timing requirement. More modifiers mean harder debugging.
The once modifier is handy for analytics or “load on first reveal” patterns where repeat events should not refetch. throttle differs from delay: throttle caps frequency, delay waits for quiet time. Pick the one that matches user behavior.
Enable Network throttling, type quickly in a search field, and confirm the final #results content always matches the current input. If stale results appear, add or tighten hx-sync. Log the trigger string in htmx:beforeRequest while debugging. It shows exactly which clause fired.
Lesson completed