skip to Main Content

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:

  1. Form should be re-rendered on error (400 Bad Request)
  2. User should be redirected to their profile page on success (200 OK)

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?

2

Answers


  1. Chosen as BEST ANSWER

    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).


  2. The problem seems to be that the hx-target attribute is taking precedence over the HX-Location header. The hx-target attribute instructs HTMX where to place the response, while HX-Location header from the server suggests a redirect.

    For testing, try and use a small piece of JavaScript with HTMX to handle the redirection based on the HX-Location header, overriding the default behavior of HTMX in this scenario.

    Add an hx-trigger attribute to your form to specify a custom JavaScript function that will handle the htmx:afterOnLoad event, which fires after HTMX processes a response:

    <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" hx-trigger="handleResponse">
            ...
            <button type="submit">Log in</button>
        </form>
    </div>
    

    Define the handleResponse function in your JavaScript code. That function will check for the HX-Location header in the HTMX response and perform a redirection if it is present:

    function handleResponse(event) {
        // Extract the HX-Location header from the HTMX response
        var hxLocation = event.detail.xhr.getResponseHeader('HX-Location');
        
        // If the HX-Location header is present, perform a redirection
        if (hxLocation) {
            window.location.href = hxLocation;
        }
    }
    

    If the server responds with a HX-Location header, the handleResponse function will catch it and redirect the user to the specified URL, overriding the default behavior of HTMX in this scenario.

    On the other hand, if the server responds with a 400 status code, the hx-target-400 attribute will still work as intended, and HTMX will re-render the form with the outlined errors.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search