#htmx #html #frontend

Day 10: Server-Side Validation

Welcome to Day 10.

In a SPA, you validate JSON responses. In htmx, you return HTML with errors.

The Pattern

  1. User submits form.
  2. Server checks data.
  3. If invalid -> Return the Form HTML again, but with error messages and values filled in.
  4. If valid -> Return success message or redirect.

Inline Validation (UX)

You want real-time feedback? Trigger on change or blur.

<input 
    name="email" 
    hx-post="/validate/email" 
    hx-trigger="blur"
    hx-target="#email-error"
/>
<span id="email-error"></span>

Server Response (if invalid): <span style="color:red">Email already taken</span>

Server Response (if valid): <span>✅</span>

Handling HTTP Statuses

By default, htmx ignores 4xx and 5xx error responses (it doesn’t swap). But for validation (422 Unprocessable Entity), we want to swap (to show the error form).

<!-- Enable swapping on error ranges -->
<body hx-ext="response-targets">
 ...
</body>

Or, simpler: Just return 200 OK containing the form errors. This is often the pragmatic htmx way.

Challenge for Day 10

  1. Create a “Sign Up” form.
  2. Username, Email.
  3. If Username is “admin”, the server should return the form again with an error “Reserved name”.
  4. Use hx-target="this" (replace the whole form).

Solution:

<!-- form.html template -->
<form hx-post="/signup" hx-swap="outerHTML">
    <label>Username</label>
    <input name="username" value="admin" class="error">
    <div class="error-msg">Reserved name</div>
    
    <button>Submit</button>
</form>

The server literally re-renders the template with the error state included.

Tomorrow: Infinite Scroll.