Building HTMX-powered interfaces with ECA¶
HTMX lets you build dynamic, interactive interfaces by
adding attributes to HTML elements, without writing JavaScript. Drupal core
ships HTMX and a small integration layer, and the eca_htmx module exposes
that integration to ECA models. This lets you build auto-refreshing regions,
click-to-load fragments, and dynamic responses entirely from the modeler.
This guide explains what Drupal core provides, which ECA plugins map to those features, and how to combine them into working patterns.
How HTMX works in Drupal¶
HTMX is a declarative markup system. You add data-hx-* attributes to an
element, and the HTMX JavaScript library turns them into AJAX requests that
swap the response into the page. For example, an element with
data-hx-get="/clock" and data-hx-trigger="every 1s" polls /clock once a
second and replaces its own content with the response.
Drupal core provides three building blocks:
- The
core/drupal.htmxlibrary — the HTMX runtime plus Drupal glue that re-attaches Drupal behaviors to swapped-in content and loads any new CSS and JavaScript the response requires. - The minimal response renderer — when a request is marked as an HTMX
request, core returns only the page's main content wrapped in a bare HTML
document instead of the full themed page (header, blocks, and footer are
omitted). The minimal response also carries an
X-Robots-Tag: noindexheader so the fragment is not indexed by search engines. - HTMX request and response headers — HTMX sends
HX-*request headers (such asHX-RequestandHX-Trigger) and honorsHX-*response headers (such asHX-RedirectandHX-Trigger) to coordinate client behavior.
The eca_htmx module builds entirely on these core building blocks. It never
ships its own HTMX JavaScript, and it produces all attributes and headers
through core's HTMX helper, so the markup stays consistent with the rest of
Drupal.
The two ways to request a minimal response¶
A recurring source of confusion is that core offers two independent ways to get the minimal (main-content-only) response, and they take effect at different stages of the request lifecycle. They are not interchangeable.
_htmx_routeroute option- Set on a route while routes are being built. Any request to a route carrying this option returns the minimal response. Use the HTMX: mark route action, which reacts to the Alter route event.
_wrapper_format=drupal_htmxquery parameter- Added to an individual request at runtime. Only that request returns the minimal response. Use the HTMX: minimal response action, or let the polling and element actions add it automatically through their only main content option.
Which one to use
Mark the route when you control the route and want every request to it to return a fragment (for example, a dedicated endpoint that only ever serves a fragment). Mark the request when you want a specific interaction to fetch a fragment from a route that otherwise renders a full page.
The plugins¶
Building HTMX elements¶
- HTMX: render element
- Builds a single element carrying the HTMX attributes you configure: the request method and URL, the trigger, the swap strategy, the target and select selectors, and options such as a confirmation dialog, indicators, pushed URLs, and request values. Use this for click-to-load fragments, infinite scroll, and similar interactions.
- HTMX: poll region
- A specialized element that polls a URL on an interval and swaps in the response. Use it for content that refreshes on its own, such as a clock, a status indicator, or a notification count. The only main content option is enabled by default, so the polled URL automatically returns a fragment.
Both actions render an element. Place them in a block, an entity display, or
any other render context, and they attach core/drupal.htmx automatically.
Reacting to HTMX requests¶
- HTMX: is request
- A condition that is true when the current request is an HTMX request. Use it to branch a model so that it builds a fragment for HTMX requests and a full page otherwise.
- HTMX: compare request value
- A condition that compares a value from the current HTMX request — such as the target element, the trigger, or the current URL — against an expected value.
The same request information is available as tokens, so you can read the HTMX target or trigger anywhere a token is accepted.
Shaping HTMX responses¶
- HTMX: set response header
- Sets any of the HTMX
HX-*response headers on the current response, for exampleHX-Redirectto redirect the client,HX-Triggerto fire a client-side event, orHX-Retargetto change where the response is swapped. TheHX-Locationheader supports its full form (source, event, handler, target, swap, values, headers, and select).
Because this action shapes the response, it reacts to a response event such as the Response created event or an ECA endpoint response.
Serving fragments with ECA endpoints¶
The natural source for an HTMX fragment is an ECA endpoint. An endpoint gives you a URL that an ECA model fully controls: the model builds the response content and can attach HTMX response headers. Because you control the endpoint route, its response is already a fragment — no full page chrome to strip — and it pairs naturally with a polling region or a click-to-load element that points at it.
Common patterns¶
Auto-refreshing region¶
- Event: any event that builds a render element, such as a block build.
- Action: HTMX: poll region — set the URL to an endpoint that returns the fragment, and the interval in seconds.
The region polls the endpoint and swaps in the response on every interval. Leave only main content enabled so the endpoint returns a fragment.
Click-to-load content¶
- Event: any event that builds a render element.
- Action: HTMX: render element —
set the method to
GET, the URL to the fragment endpoint, the trigger toclick, and the target to the element that should receive the content.
Serve a fragment from an endpoint¶
- Event: ECA endpoint response — define the endpoint path.
- Action: Set response content — build the fragment markup.
- Action (optional):
HTMX: set response header —
fire a client-side event with
HX-Trigger, for example to notify other parts of the page that the fragment refreshed.
Turn an existing route into a fragment¶
- Event: Alter route.
- Action: HTMX: mark route —
set the route name (a
*wildcard is supported) to mark as an HTMX route.
Every request to a marked route then returns the minimal response.
Related resources¶
- HTMX: render element — action reference
- HTMX: poll region — action reference
- HTMX: mark route — action reference
- HTMX: minimal response — action reference
- HTMX: set response header — action reference
- HTMX: is request — condition reference
- HTMX: compare request value — condition reference
- Choosing the right request and response events — guide
- HTMX Blocks — library example