Skip to content

Request/Response Lifecycle

When to Use

You need to understand how HTMX requests flow through Drupal's render pipeline to debug issues or build custom integrations.

Steps

  1. Request Initiated — User interacts with HTMX-enabled element (button click, form change, etc.)

  2. Request Configuration (htmx:configRequest event) — JavaScript adds parameters:

  3. _wrapper_format=drupal_htmx (if data-hx-drupal-only-main-content present)
  4. ajax_page_state parameters for differential asset loading
  5. _triggering_element_name from HX-Trigger-Name header

Reference: /core/misc/htmx/htmx-assets.js lines 39-62

  1. Server Processing — Request routes to controller/form, Drupal detects HTMX via headers

  2. Response Generation — Controller returns render array with HTMX attributes/headers applied via Htmx class

  3. Response RenderingHtmxRenderer creates minimal HTML response:

    <!doctype html>
    <html>
    <head>
    <meta name="robots" content="noindex">
    <title>Page Title</title>
    <css-placeholder token="...">
    <js-placeholder token="...">
    </head>
    <body>
    <!-- Status messages -->
    <!-- Main content -->
    </body>
    </html>
    

Reference: /core/lib/Drupal/Core/Render/MainContent/HtmxRenderer.php lines 53-73

  1. Asset Loading (htmx:beforeSwap event) — JavaScript extracts and loads new CSS/JS files not already on page

Reference: /core/misc/htmx/htmx-assets.js lines 84-146

  1. Content Swap — HTMX swaps content according to swap strategy (outerHTML, innerHTML, etc.)

  2. Behaviors Attach (htmx:drupal:load event) — Drupal behaviors run on new content

Reference: /core/misc/htmx/htmx-behaviors.js lines 14-16

Decision Points

At this step... If... Then...
Request Configuration Element has data-hx-drupal-only-main-content Add _wrapper_format=drupal_htmx to trigger HtmxRenderer
Server Processing Route has _htmx_route: TRUE HtmxRenderer automatically invoked by HtmxContentViewSubscriber
Response Rendering Request has _wrapper_format=drupal_htmx OR route has _htmx_route: TRUE HtmxRenderer creates minimal response instead of full page
Asset Loading Response includes new CSS/JS loadjs loads only files not in ajax_page_state.libraries

Common Mistakes

  • Not understanding onlyMainContent() vs _htmx_route — Both trigger HtmxRenderer but through different mechanisms
  • Expecting full page HTML — HtmxRenderer returns minimal structure with noindex meta tag
  • Not accounting for asset loading delay — Behaviors fire AFTER assets load, not immediately after swap
  • Forgetting history cleanup — htmx:beforeHistoryUpdate removes wrapper_format from URLs

See Also

  • Previous: HTMX vs AJAX Decision
  • Next: Basic Setup
  • Reference: /core/lib/Drupal/Core/EventSubscriber/HtmxContentViewSubscriber.php — Handles _htmx_route option