Baptiste LEROYER
Baptiste LEROYER

Reputation: 33

No DOM update with HTMX and GoLang

I'm trying to learn HTMX with Go and GoFiber.

Here is my HTML page :

<script src="https://unpkg.com/[email protected]" integrity="sha384-wS5l5IKJBvK6sPTKa2WZ1js3d947pvWXbPJ1OmWfEuxLgeHcEbjUUA5i9V5ZkpCw" crossorigin="anonymous"></script>
<main>
    <div class="grid h-screen place-items-center">
        <div class="flex flex-col items-center space-y-4">
            <h1 class="text-5xl font-bold mb-16">Connexion</h1>
            <form hx-post="/auth" hx-target="#error-message" hx-swap="innerHTML" class="flex flex-col items-center space-y-4">
                <input
                    type="password"
                    placeholder="Mot de passe"
                    class="input input-bordered input-primary w-full max-w-xs"
                    id="password"
                    name="password"
                />
                <button type="submit" class="btn btn-primary">Connexion</button>
            </form>
            <div id="error-message" class="text-red-500"></div>
        </div>
    </div>
</main>

and here is the /auth route of my API in GoFiber

func Auth(c *fiber.Ctx) error {
    // get the password on the body
    clientPassword := c.FormValue("password")

    // check if the password is correct
    password, err := database.GetPassword()
    if err != nil {
        log.Fatalf("Failed to get the password: %v", err)
        return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error : cannot get the password in db")
    }

    if clientPassword != password {
        log.Println("Incorrect password")
        return c.Status(fiber.StatusUnauthorized).SendString("<p class='text-red-500'>Incorrect password. Please try again.</p>")
    }

    log.Println("Correct password")

    // redirect the client on the home page
    return c.Redirect("/videos")
}

My problem is that when I send an incorrect password, the API correctly receives the request and my browser correctly receives the response with a status code of 401 and the HTML string. However, the message sent by the API does not appear in the error-message div. Why didn't it work, and how can I fix this?

(I tried swapping the outerHTML, targeting a class insted of an id but nothing seem to work.)

Upvotes: 0

Views: 187

Answers (1)

Gimby
Gimby

Reputation: 5274

HTMX by default only processes successful requests. If you want to handle 401 responses, you have two basic choices. I would say up front that I am not a fan of using 401 for this purpose, I would use 422 instead which is "unprocessable entity". It is a better fit for what is essentially a validation type of error from the perspective of a login form. Your mileage may vary.

Option 1: Use an extension library

https://github.com/bigskysoftware/htmx-extensions/blob/main/src/response-targets/README.md

If you use it, be aware that it is not enough to include the script in your page. You also need to activate it using hx-ext : https://htmx.org/docs/#extensions

Example setup:

<script src="https://unpkg.com/[email protected]/response-targets.js"></script>
<body hx-ext="response-targets">

<form hx-post="/auth" hx-target-422="#error-message"

Option 2: Tell HTMX that it should process specific status codes

Adding a whole different extension library just to get one task done might seem overkill; I wouldn't want to riddle my front end with large amounts of status-code specific target directives. Fortunately HTMX is quite configurable. You can tell it that you do want to "swap" on specific response codes. https://htmx.org/docs/#requests

Example:

document.body.addEventListener('htmx:beforeSwap', function(evt) {
  if(evt.detail.xhr.status == 422) {
    evt.detail.shouldSwap = true;
    evt.detail.isError = false;
  }
});

Rinse and repeat for any other error status codes you would want to handle in your front-end. Just keep in mind that if you start to put a long list of response codes here... you may want to rethink if you actually need HTMX for your use case.

Upvotes: 0

Related Questions