htmx Tutorial · Going Further · Lesson 24 of 30

Response Headers

Let the server control what happens next: redirect, refresh, retarget the swap, change the swap style, or push a URL.

Create a free account to save this page, take notes and track your progress. Sign in

Headers the server can send

Header Effect
HX-Trigger fire client-side events (a name, or JSON with details: {"showMessage": "Saved"})
HX-Redirect do a full browser redirect to a URL
HX-Location navigate to a URL with an htmx request (no full reload)
HX-Refresh true: reload the whole page
HX-Push-Url / HX-Replace-Url change the address bar
HX-Retarget swap into a different element (a CSS selector)
HX-Reswap use a different swap style
HX-Reselect choose part of the response, like hx-select

These let the server decide based on the result. A login form, for example, returns the form with an error, or HX-Redirect: /dashboard on success. (HX-Redirect is used instead of a normal 302 because htmx's request would follow a 302 silently and swap the dashboard HTML into the form.)

HX-Retarget and HX-ReswapTry it yourself
<form hx-post="/comments" hx-target="#comments" hx-swap="beforeend">
  <input name="text" placeholder="Write a comment (try 'spam')"> <button>Post</button>
</form>
<ul id="comments"></ul>
<p id="flash" style="color:#b91c1c"></p>

<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
  server.post("/comments", (req) => {
    const text = req.body.text || "";
    if (/spam/i.test(text))   // the server changes where and how the response is swapped
      return { body: "Comments that look like spam aren't allowed.",
               headers: { "HX-Retarget": "#flash", "HX-Reswap": "innerHTML" } };
    return `<li>${server.escape(text)}</li>`;
  });
</script>

Sending data with HX-Trigger

HX-Trigger accepts JSON. Each key is an event name, and its value arrives in event.detail.value. The event is fired on the element that made the request and bubbles up, so any ancestor (or document.body) can listen. A common use is a toast message. (Use lower-case, dash-separated event names with hx-on: HTML attribute names can't keep capital letters.)

A toast from HX-Trigger JSONTry it yourself
<style>#toast { position: fixed; right: 8px; top: 8px; background: #15803d; color: #fff; padding: 6px 10px;
  border-radius: 6px; display: none; }</style>
<!-- HX-Trigger fires the event on the button; it bubbles up to this div -->
<div hx-on:show-message="const t = document.getElementById('toast'); t.textContent = event.detail.value;
                         t.style.display = 'block'; setTimeout(() => t.style.display = 'none', 2000)">
  <button hx-post="/settings" hx-swap="none">Save settings</button>
</div>
<div id="toast"></div>

<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
  server.post("/settings", () => ({ body: "", headers: { "HX-Trigger": JSON.stringify({ "show-message": "Settings saved" }) } }));
</script>

Test yourself

Why use HX-Redirect instead of a normal 302 redirect for an htmx login form?

  1. htmx's request follows a 302 silently and would swap the new page into the form
  2. 302 is not allowed for POST
  3. HX-Redirect is faster
  4. Browsers block 302 responses to htmx
Show answer

Answer: htmx's request follows a 302 silently and would swap the new page into the form

XMLHttpRequest follows redirects transparently; HX-Redirect asks htmx to change the whole page instead.

Was this page helpful?