I have a login form marked up like this:
<div id="login_form" hx-ext="response-targets">
<form action="/login" method="POST" hx-boost="true" hx-target="#login_form" hx-target-400="#login_form" hx-swap="innerHTML">
...
<button type="submit">Log in</button>
</form>
</div>
When there's an error, backend returns the form with outlined errors, with 400 status code (hence response-targets
extension). On success, backend responds HX-Location
header of user's profile page, where I expect user to be redirected. Put simply:
What actually happens is that HTMX renders entire user's profile page in #login_form
instead of redirecting, as if hx-target
overrides or takes precedence over HX-Location
header.
Tried this without response-target
plugin, it works the same. With response-target
plugin I can't omit hx-target
because then hx-target-400
is not recognized or handled.
How can I put it together so forms are re-rendered on errors, or redirected to a page on success?
Behavior where hx-target
is populated with the whole page that I wanted to redirect to happens when both Location
and HX-Location
headers are present.
Fix is simple - if backend detects that request is coming from HTMX (by checking if HX-Request
request header exists), it responds with HX-Location
redirection, and if not it responds with Location
header.
Reason why I was sending both headers is because I started with an idea of progressive enhancement. My assumption was that HTMX (v1.9.6) will use HX-Location
when it finds it, with Location
left as a fallback for request not coming form HTMX (or with JavaScript disabled).