HTMX Triggers — Complete Guide with Examples
In this tutorial, you'll learn about HTMX triggers. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
HTMX triggers define what event initiates an HTTP request, supporting standard DOM events, custom events, polling intervals, and trigger modifiers like debounce, throttle, and delay.
What You'll Learn
By the end of this tutorial, you'll configure click, load, input, every, and custom triggers, use modifiers like delay and throttle, combine multiple triggers, and filter events with CSS selectors.
Why It Matters
Choosing the right trigger makes your UI feel responsive. A search that fires on every keystroke overwhelms the server. A search that fires 300ms after typing stops feels snappy. Polling every 5 seconds keeps dashboards fresh without excessive requests.
Real-World Use
Durga Antivirus Pro's real-time dashboard uses multiple triggers: every 5 seconds for auto-refresh, mouseenter for tooltip previews, load for initial data, and custom events for inter-component communication.
Where This Fits in Your Learning Path
flowchart LR
A["HTMX Targets"] --> B["**HTMX Triggers**"]
B --> C["Swapping & Transitions"]
C --> D["Synchronization"]
D --> E["Advanced HTMX"]
style B fill:#3b82f6,stroke:#2563eb,color:#fff
style A fill:#e2e8f0,stroke:#94a3b8
style E fill:#e2e8f0,stroke:#94a3b8
Standard Triggers
HTMX uses standard DOM events as triggers.
<!-- Click (default for buttons, anchors, form submits) -->
<button hx-get="/api/click">Click me</button>
<!-- Double click -->
<div hx-get="/api/double-click" hx-trigger="dblclick">Double-click me</div>
<!-- Focus -->
<input hx-get="/api/autocomplete" hx-trigger="focus" hx-target="#suggestions">
<!-- Blur (lost focus) -->
<input hx-post="/api/validate" hx-trigger="blur" hx-target="#validation">
Expected output: Each element fires its request on the specified DOM event.
The "load" Trigger
Fires the request immediately when the element is loaded into the DOM.
<!-- Lazy load content on page load -->
<div hx-get="/api/sidebar" hx-trigger="load">
Loading sidebar...
</div>
<!-- Lazy load when an element is added dynamically -->
<div hx-get="/api/comments" hx-trigger="load" hx-target="#comments">
Loading comments...
</div>
<div id="comments"></div>
Expected output: The request fires as soon as the element is parsed. The element shows "Loading..." until the response arrives.
The "every" Trigger (Polling)
Creates a polling interval that fires the request repeatedly.
<!-- Poll every 5 seconds -->
<div hx-get="/api/status" hx-trigger="every 5s">
Status updated every 5 seconds
</div>
<!-- Poll with different interval -->
<div hx-get="/api/clock" hx-trigger="every 1s" hx-target="#clock">
<span id="clock"></span>
</div>
<!-- Polling that stops on certain conditions -->
<div hx-get="/api/job-status" hx-trigger="every 2s" hx-target="#job-result">
Checking job status...
</div>
Expected output: The request fires repeatedly at the specified interval. The clock updates every second, status every 5 seconds.
The "input" and "change" Triggers
Input triggers respond to user input events.
<!-- Fire on every input change (with debounce) -->
<input hx-get="/api/search"
hx-trigger="input changed delay:300ms"
hx-target="#results"
placeholder="Type to search">
<!-- Fire only when value actually changes (not same as previous) -->
<input hx-get="/api/validate"
hx-trigger="change"
hx-target="#validation-message">
<!-- Input with throttle (limit frequency) -->
<input hx-get="/api/live-preview"
hx-trigger="input throttle:1s"
hx-target="#preview">
Expected output: The search debounces (waits 300ms after last keystroke). The change trigger fires only when the user blurs with a different value.
Trigger Modifiers
Modifiers refine trigger behavior.
<!-- once: fire only one time -->
<button hx-get="/api/one-time" hx-trigger="click once">
Can only click once
</button>
<!-- delay: wait before firing -->
<button hx-get="/api/delayed" hx-trigger="click delay:500ms">
Waits 500ms before firing
</button>
<!-- throttle: limit frequency -->
<button hx-post="/api/rapid-click"
hx-trigger="click throttle:2s">
Max once per 2 seconds
</button>
<!-- from: listen on a different element -->
<button hx-get="/api/proxy"
hx-trigger="click from:#submit-btn"
hx-target="#result">
Triggered by #submit-btn
</button>
Expected output: once prevents double-clicks. delay adds a wait. throttle limits frequency. from listens on a different element.
Custom Events
HTMX listens to custom DOM events as triggers.
<div hx-get="/api/data-refresh"
hx-trigger="data-updated from:body">
Listens for custom data-updated event
</div>
<button onclick="document.dispatchEvent(new CustomEvent('data-updated'))">
Trigger refresh from anywhere
</button>
<!-- Filtered custom event -->
<div hx-get="/api/notification"
hx-trigger="notify[type=='success']">
Only fires for success notifications
</div>
Expected output: The first div reacts to the custom 'data-updated' event dispatched anywhere on the page.
Combining Multiple Triggers
Separate multiple triggers with commas.
<!-- Fire on click OR load -->
<button hx-get="/api/data" hx-trigger="click, load">
Loads on click and on page load
</button>
<!-- Input with both change and search -->
<input hx-get="/api/search"
hx-trigger="input changed delay:300ms, search"
hx-target="#results">
<!-- Polling with manual refresh -->
<div hx-get="/api/dashboard"
hx-trigger="every 30s, click from:#refresh-btn">
Dashboard auto-refresh
</div>
Expected output: Multiple triggers mean the request fires on any of the specified conditions.
Common Mistakes
1. Using "change" instead of "input" for real-time updates
change fires on blur, not on every keystroke. Use "input changed delay:300ms" for live search.
2. Forgetting the "changed" keyword with input
"input" without "changed" fires on every keystroke including the same value. "input changed" fires only when the value differs.
3. Polling too frequently
Every 1s polling on many elements can overwhelm the server. Use 5s or longer for most use cases.
4. Not using "once" for one-time actions
Delete buttons without once can fire multiple times if clicked rapidly, causing server errors.
5. Using "from" with a non-existent selector
The from modifier waits for events on a specific element. If the element doesn't exist, the trigger never fires.
Practice Questions
What is the default trigger for buttons? Click. Buttons fire the request on click by default.
How do you create a debounced search? Use hx-trigger="input changed delay:300ms" on the search input.
What does the "once" modifier do? The request fires only one time, then the trigger is removed.
How do you poll every 10 seconds? Use hx-trigger="every 10s" on the element.
What is the "from" modifier used for? It listens for the trigger event on a different element, not the one with the HTMX attribute.
Challenge
Build a dashboard with multiple triggers: initial data loads on page load, auto-refreshes every 30 seconds, has a manual refresh button, and handles a custom "data-updated" event from other components.
FAQ
Mini Project
Build a real-time monitoring dashboard. Use multiple triggers: load for initial data fetch, every 5s for auto-refresh, mouseenter for detail tooltips, and a custom event for inter-widget communication.
<div hx-get="/api/dashboard/header" hx-trigger="load" hx-target="#header">
<div id="header">Loading header...</div>
</div>
<div hx-get="/api/dashboard/metrics"
hx-trigger="every 5s, data-refreshed from:body"
hx-target="#metrics">
<div id="metrics">Loading metrics...</div>
</div>
<div hx-get="/api/dashboard/alerts"
hx-trigger="every 10s, click from:#refresh-alerts"
hx-target="#alerts">
<div id="alerts">
<span hx-get="/api/alerts/tooltip"
hx-trigger="mouseenter"
hx-target="next .tooltip">
Alerts
</span>
<div class="tooltip"></div>
</div>
<button id="refresh-alerts">Refresh Now</button>
</div>
<button onclick="document.dispatchEvent(new CustomEvent('data-refreshed'))">
Force Refresh All
</button>
What's Next
Master swapping strategies:
| Tutorial | What You'll Learn |
|---|---|
| HTMX Swapping | Swap strategies and CSS transition animations |
| HTMX Synchronization | Coordinate multiple HTMX requests |
Related topics: DOM events reference, debounce and throttle patterns.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro