Complete Guide to htmx Lifecycle Events: A Comprehensive Reference
htmx fires over 40 built-in lifecycle events—prefixed with htmx:—that allow developers to hook into every phase of element processing, AJAX requests, DOM swaps, history navigation, and form validation.
The bigskysoftware/htmx library emits these events at specific moments during its execution pipeline, all triggered via the internal triggerEvent helper in src/htmx.js. By listening to these events, you can intercept requests, modify headers, handle errors, or execute cleanup code without writing custom extensions.
Complete List of htmx Lifecycle Events by Phase
The htmx source code organizes lifecycle events into distinct phases. Below is the complete reference derived from the implementation in src/htmx.js.
Element Processing Events
These events fire when htmx initializes or cleans up DOM nodes:
htmx:beforeProcessNode— Fired before htmx processes a newly added node. Triggered at line 2947 insrc/htmx.js.htmx:afterProcessNode— Fired after a node has been fully processed. Triggered at line 3064.htmx:beforeCleanupElement— Emitted just before htmx cleans up an element, such as during swap removal (line 1686).
Loading Events
Control behavior after content insertion and script evaluation:
htmx:load— Runs after new content has been inserted and any scripts have been evaluated (line 875).htmx:afterLoad(aliashtmx:afterOnLoad) — Triggered after thehtmx:onLoadcallbacks complete (line 4810).htmx:onLoadError— Fired when an error occurs while invoking anhtmx:onLoadhandler (line 4600).
Request Lifecycle Events
Intercept and modify AJAX requests at various stages:
htmx:configRequest— Allows extensions to modify request configuration before transmission (line 4491).htmx:beforeRequest— Fired before the XHR/fetch request initiates. Returningfalseaborts the request (line 4627).htmx:beforeSend— Fired right before the request sends; useful for adjusting headers (line 4646).htmx:afterRequest— Fires after the request completes, regardless of success (line 4581).htmx:sendError— Emitted when the XHR/fetch call fails due to network errors (line 4609).htmx:sendAbort— Fired when a request is aborted programmatically (line 4615).htmx:timeout— Triggered when a request exceeds the configured timeout (line 4622).htmx:beforeOnLoad— Fired before the response is passed tohtmx:onLoadcallbacks (line 4810).
Swap Phase Events
Control the DOM insertion and settlement process:
htmx:beforeSwap— Fired before the HTML fragment swaps into the DOM. Returningfalsecancels the swap (line 4883).htmx:afterSwap— Fired after the swap completes (line 1982).htmx:swapError— Fired when a swap cannot be performed, such as when the target is invalid (line 2055).htmx:afterSettle— Fired after the settle phase completes, including attribute updates and class changes (line 2000).htmx:beforeTransition— Fired right before any CSS transition associated with a swap starts (line 2029).
History Handling Events
Manage browser history navigation and caching:
htmx:historyItemCreated— When a new history entry is created (line 3186).htmx:beforeHistorySave— Before the current page state saves to session storage (line 3265).htmx:historyCacheMiss— When history navigation fails to find a cached entry (line 3333).htmx:historyCacheHit— When a cached history entry is successfully used (line 3348).htmx:historyCacheMissLoad— After a cache-miss load attempt finishes (line 3322).htmx:historyRestore— When the document restores from a history navigation (line 3328).htmx:historyCacheMissLoadError— Errors occurring while loading a page after a cache miss (line 3333).htmx:historyCacheError— General errors while reading or writing the history cache (line 3199).htmx:beforeHistoryUpdate— Before the URL is pushed or replaced in browser history (line 4956).htmx:pushedIntoHistory— After a new state pushes onto the history stack (line 4959).htmx:replacedInHistory— After a state is replaced viareplaceState(line 4962).
Validation Events
Hooks for the htmx:validation: namespace:
htmx:validation:validate— Fired when a form is about to be validated by htmx (line 3564).htmx:validation:failed— When validation fails; useful for custom error UI (line 3567).htmx:validation:halted— Emitted when validation stops further processing (line 3450).
Error Handling Events
Capture failures across the pipeline:
htmx:error— Generic error hook for any failure in the htmx pipeline (line 3114).htmx:responseError— Specific to non-2xx HTTP responses (line 4969).htmx:targetError— When the target selector cannot be resolved (line 4292).htmx:evalDisallowedError— When expression evaluation is blocked by CSP (line 3974).htmx:badResponseUrl— Emitted if the response URL cannot be parsed (line 4035).htmx:syntax:error— When htmx internal parsing encounters invalid syntax (line 2180).htmx:eventFilter:error— Errors arising inside custom event-filter functions (line 2482).
Out-of-Band (OOB) Swap Events
Handle content swaps targeting elements outside the primary swap target:
htmx:oobBeforeSwap— Prior to performing an OOB swap (line 1496).htmx:oobAfterSwap— After an OOB swap completes (line 1505).htmx:oobErrorNoTarget— When an OOB swap cannot find its target (line 1512).
User Interaction and Security Events
Control confirmation dialogs and prompt flows:
htmx:confirm— Before a confirmation dialog; returningfalseaborts the request (line 4324).htmx:prompt— Before a prompt dialog; the returned value is used as request data (line 4417).htmx:abort— Sent to abort an ongoing request, often from an extension (line 4356).
Miscellaneous Events
Additional lifecycle hooks:
htmx:xhr:<event>— Low-level XHR events such ashtmx:xhr:loadandhtmx:xhr:error(line 4638).revealed(non-prefixed) — Fired once an element becomes visible after a swap, used by demo themes (line 2635).
How to Listen for htmx Lifecycle Events
All htmx events bubble and can be captured using standard DOM event listeners or the htmx.on() helper. Event handlers receive an event object with a detail property containing context-specific data.
Basic Event Listening Patterns
// Run code after new content loads and scripts execute
htmx.on("htmx:load", function (evt) {
console.log("Content loaded into:", evt.detail.elt);
});
// Cancel requests conditionally
htmx.on("htmx:beforeRequest", function (evt) {
if (!confirm("Proceed with this action?")) {
return false; // Abort the request
}
});
// Modify request headers dynamically
htmx.on("htmx:configRequest", function (evt) {
evt.detail.headers["X-Request-ID"] = crypto.randomUUID();
});
// Execute code after DOM settlement
htmx.on("htmx:afterSettle", function (evt) {
evt.detail.target.querySelectorAll('.animate').forEach(el => {
el.classList.add('visible');
});
});
// Handle validation failures
htmx.on("htmx:validation:failed", function (evt) {
console.warn("Validation errors:", evt.detail.errors);
});
Using Event Detail Properties
Most htmx lifecycle events include a detail object with contextual information:
elt— The element that triggered the htmx actiontarget— The target element for the swaprequestConfig— Configuration object for the request (inhtmx:configRequest)successful— Boolean indicating if the request succeeded (inhtmx:afterRequest)failed— Boolean indicating if the request failed (inhtmx:afterRequest)
Key Source Files and Implementation Details
Understanding where these events originate helps with debugging and extension development:
src/htmx.js— The core implementation containing all lifecycle event triggers via thetriggerEventhelper function. This is the authoritative source for event names and timing.dist/htmx.js— The compiled distributable that mirrors the source events.test/core/events.js— The test suite verifying that each lifecycle event fires at the correct moment with proper parameters.
Events are dispatched using htmx's internal triggerEvent function, which wraps the native CustomEvent constructor and ensures consistent bubbling and cancelation behavior across browsers.
Summary
- htmx lifecycle events provide granular hooks into every phase of the request-response cycle, organized into phases: element processing, loading, requests, swaps, history, validation, and errors.
- Returning
falsefrom events likehtmx:beforeRequestorhtmx:beforeSwapcancels the default behavior, enabling conditional request logic. - Event detail objects contain contextual information about the triggering element, target, and request configuration.
- All events use the
htmx:prefix (exceptrevealed) and are implemented insrc/htmx.jsusing the internaltriggerEventmechanism.
Frequently Asked Questions
How do I cancel an htmx request using lifecycle events?
Listen for htmx:beforeRequest or htmx:beforeSwap and return false from your handler. According to the source code in src/htmx.js at line 4627, returning false from htmx:beforeRequest prevents the XHR/fetch call from initiating. Similarly, returning false from htmx:beforeSwap (line 4883) prevents the DOM modification while still allowing the request to complete.
What is the difference between htmx:afterSwap and htmx:afterSettle?
htmx:afterSwap fires immediately after the HTML fragment inserts into the DOM (line 1982), while htmx:afterSettle fires after all settlement tasks complete, including attribute updates, class modifications, and child element processing (line 2000). Use htmx:afterSwap for immediate DOM manipulation, and htmx:afterSettle when you need to interact with elements after htmx has fully initialized them.
Can I modify AJAX headers using htmx lifecycle events?
Yes. The htmx:configRequest event (line 4491) fires before the request configuration finalizes, allowing you to modify evt.detail.headers, evt.detail.parameters, or the HTTP method. For last-minute header adjustments after the XHR object creates but before it sends, use htmx:beforeSend at line 4646.
Which event should I use to detect when new content enters the DOM?
Use htmx:load (line 875) to detect when new content has been inserted and any inline scripts have been evaluated. This event bubbles and provides access to the inserted element via event.detail.elt. For code that should run after every AJAX request regardless of swap mode, use htmx:afterRequest (line 4581), which fires even if the swap fails.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →