htmx 4.0 is under construction — migration guide

Bulk Actions

Perform actions on multiple records

Basic usage

On the client, wrap a table in a <form> with checkboxes for each row.

<form id="checked-contacts" hx-post="/users" hx-swap="innerHTML settle:3s" hx-target="#toast"> <table> <thead> <tr> <th>Name</th> <th>Email</th> <th>Active</th> </tr> </thead> <tbody> <tr> <td>Joe Smith</td> <td>joe@smith.org</td> <td><input type="checkbox" name="active:joe@smith.org"></td> </tr> ... </tbody> </table> <input type="submit" value="Bulk Update" class="btn primary"> <output id="toast"></output> </form>
  • hx-post sends all checked values to /users.
  • hx-swap="innerHTML settle:3s" swaps the toast content, then fades it out after 3 seconds via the htmx-settling class.
  • hx-target="#toast" directs the response into the toast element.

On the server, bulk-update statuses based on which checkboxes were checked and respond with a message.

Activated 2 and deactivated 1 users

The <output> element announces the result for screen readers. For general-purpose messages outside a form, use an ARIA live region instead, e.g. <p id="toast" aria-live="polite"></p>.

Notes

No re-render needed

Because HTML form inputs manage their own state, the table does not need to be re-rendered after the POST. Checked rows stay checked.

Toast fade-out

The toast uses htmx-settling to control opacity. When htmx swaps in the response, it adds htmx-settling (opacity 100), then removes it after the settle time (3s), triggering the CSS transition back to opacity 0.