【htmx】行を選択して一括更新
参考 #
実際のコード #
<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 id="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>
公式htmxの サンプルコードです。
概要 #
チェックボックスで選択されたユーザーを/users
エンドポイントに POST
で送信し、結果メッセージを #toast
に表示するというバルク更新。
解説 #
formタグ #
<form id="checked-contacts"
hx-post="/users"
hx-swap="innerHTML settle:3s"
hx-target="#toast">
hx-post="/users"
: HTML form送信ではなく、 htmxで/users
にPOST
リクエストするhx-swap="innerHTML settle:3s
: SSRしたHTMLをhx-target
で指定した要素のinnerHTML
に置き換える。- また、描画が安定(settle)してから3秒間はそのまま表示する(アニメーションなどの完了待ちに使ったり)
hx-target="#toast
: レスポンス内容を描画する要素を指定(id="toast"
)
input active #
<tbody id="tbody">
<tr>
<td>Joe Smith</td>
<td>joe@smith.org</td>
<td><input type="checkbox" name="active:joe@smith.org"></td>
</tr>
...
</tbody>
name="active:joe@smith.org"
- チェックされている要素のみフォーム送信される
active:joe@smith.org=on
のような形式でサーバーに送信される
tbody
に複数行存在することが前提
submit #
<input type="submit" value="Bulk Update" class="btn primary">
<output id="toast"></output>
submit
を押すとhx-post
が発火する- SSR結果は
<output id="toast"></output>
へレンダリングされる
サーバー側の処理 #
リクエストボディ #
active:joe@smith.org=on
active:bob@tanaka.jp=on
Goのコード #
func usersHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
var activeEmails []string
for key := range r.PostForm {
if strings.HasPrefix(key, "active:") {
email := strings.TrimPrefix(key, "active:")
activeEmails = append(activeEmails, email)
}
}
fmt.Fprintf(w, "%d users updated successfully", len(activeEmails))
}
上記handlerを設定したルーティングへリクエストを送ると、2 users updasted successfully
がレスポンスとして返り<output id="toast"></output>
内へ挿入される。