Bulk Update

This demo shows how to implement a common pattern where rows are selected and then bulk updated. This is accomplished by putting a form around a table, with checkboxes in the table, and then including the checked values in the form submission(POST request):

return FormEl(
	ID("checked-contacts"),
	hx.Post("/examples/gomponents/bulk-update/"),
	hx.SwapExtended(
		swap.New().Strategy(swap.OuterHTML).Settle(3*time.Second),
	),
	hx.Target(
		"#toast",
	),

	H3(g.Text("Select Rows And Activate Or Deactivate Below")),
	Table(
		THead(
			Tr(
				Td(g.Text("Name")),
				Td(g.Text("Email")),
				Td(g.Text("Activate")),
			),
		),
		TBody(
			ID("tbody"),
			g.Group(
				g.Map(users, func(u form.UserModel) g.Node {
					return Tr(
						Td(g.Text(u.Name)),
						Td(g.Text(u.Email)),
						Td(
							Input(
								Type("checkbox"),
								Name(u.Email),
								g.If(u.Active,
									Checked(),
								),
							),
						),
					)

				}),
			),
		),
	),
	Input(
		Type("submit"),
		Value("Submit"),
	),
	UpdateToast(""),
)

The server will bulk-update the statuses based on the values of the checkboxes. We respond with a small toast message about the update to inform the user, and use ARIA to politely announce the update for accessibility.


#toast.htmx-settling {
	opacity: 100;
}

#toast {
	background: #E1F0DA;
	opacity: 0;
	transition: opacity 3s ease-out;
}
func UpdateToast(toast string) g.Node {
	return Span(
		ID("toast"),
		g.If(toast != "",
			g.Attr("aria-live", "polite"),
		),
		g.Text(toast),
	)
}

The cool thing is that, because HTML form inputs already manage their own state, we don’t need to re-render any part of the users table. The active users are already checked and the inactive ones unchecked!

You can see a working example of this code below.

Source

Demo

Select Rows And Activate Or Deactivate Below

NameEmailActivate
Joe Smith[email protected]
Angie MacDowell[email protected]
Fuqua Tarkenton[email protected]
Kim Yee[email protected]