hx-trigger: Event Filters, Debounce (delay), and Throttle Modifiers
- Last updated
- Prerequisites:
- DOM Events
- Debounce and Throttle algorithms
- htmx
- hx-trigger
- debounce
- throttle
- events
- filter
Read at your depth
The practical view
`hx-trigger` customizes which events fire an HTMX request and applies rate-limiting modifiers. Common syntax: `hx-trigger="keyup changed delay:500ms"` (debounced search), `hx-trigger="click throttle:1s"` (prevents double-clicks), `hx-trigger="load"` (fires on page load), `hx-trigger="revealed"` (fires when element scrolls into view). You can also use event filters: `hx-trigger="click[ctrlKey]"`.
The same idea in other frameworks
Custom `useDebounce(val, 500)` hook inside `useEffect`.RxJS `fromEvent(input, 'keyup').pipe(debounceTime(500), distinctUntilChanged())`.`watch(query, debounce(fn, 500))`.`hx-trigger="keyup changed delay:500ms"`.Legacy vs modern
RxJS/Lodash Debounce Implementation vs hx-trigger Modifiers
Debouncing live search manually requires external libraries and state; `hx-trigger` configures debounce in one line.
let timer; input.onkeyup = () => { clearTimeout(timer); timer = setTimeout(fetchResults, 500); }; // ❌ Verbose<input hx-get="/search" hx-trigger="keyup changed delay:500ms" hx-target="#results" /> // ✅ NEWInterview gotchas
Context
Tests your understanding of debounce vs throttle algorithms in UI events.
The mechanical answer
`delay:500ms` is a **debounce**: it waits until 500ms have elapsed *since the last event* before firing the request (ideal for typing in search boxes). `throttle:500ms` is a **rate limiter**: it fires the request immediately on first trigger, and then ignores all subsequent triggers for the next 500ms (ideal for preventing double-clicking on submit buttons).
Trap
Using `throttle` instead of `delay` on a search input will cause intermediate requests to fire mid-word while typing.
Context
Checks knowledge of cross-component event coordination in HTMX.
The mechanical answer
Use the `from:` modifier: `hx-trigger="cartUpdated from:body"`. When any element in the application dispatches `document.body.dispatchEvent(new CustomEvent('cartUpdated'))`, the targeted element catches the event and executes its `hx-get` request.
Trap
If you omit `from:body`, the element will only listen for events dispatched directly to itself or bubbling through its own children.