034. hx-disabled-elt(通信中の「連打」を優しく防ぐ)
原理:イライラと二重送信を防ぐガードマン
通信中の「空白の時間」をどう守るか
インターネットの通信には、必ず「待ち時間」が発生します。ボタンを押してからサーバーが応答するまでの、コンマ数秒、あるいは数秒。 この「空白の時間」に、ユーザーが不安になってボタンを何度も連打してしまったらどうなるでしょうか? - 注文ボタンが2回押され、同じ商品が2つ届いてしまう。 - サーバーに大量のリクエストが飛び、パンクしてしまう。 - 画面のあちこちが何度も更新され、挙動がおかしくなる。
これまでのWeb開発では、これを防ぐためにJavaScriptで「ボタンが押されたら disabled=true にし、通信が終わったら false に戻す」という、地味で面倒なコードを書くのが当たり前でした。
HTMXの hx-disabled-elt(ディセーブル・エレメント)は、この「連打防止」を完璧に自動化します。属性を添えるだけで、通信が始まった瞬間に要素を無効化し、通信が終わると魔法のように元通りにしてくれるのです。
実践:スマートな連打防止機能
1. 自分自身の無効化
最も一般的で強力な使い方です。
<!--
hx-post: 通信を実行
hx-disabled-elt: "this" (自分自身) を指定
-->
<button hx-post="/api/order" hx-disabled-elt="this">
注文を確定する
</button>
2. 複数の要素や、離れた要素を無効化する
「保存ボタン」を押した時に、離れた場所にある「キャンセルボタン」も同時に無効化したい場合の例です。
<div class="actions">
<button id="save-btn" hx-post="/save" hx-disabled-elt="#save-btn, #cancel-btn">
保存
</button>
<button id="cancel-btn" hx-get="/cancel">
キャンセル
</button>
</div>
3. ステップ・バイ・ステップ解説
- ターゲットの選定: 通信中に「動かしたくない」ボタンや入力欄はどれか決めます。
- 属性の記述:
hx-disabled-elt="セレクタ"を書きます。自分ならthis、特定のIDなら#some-idです。 - スタイルの調整: HTML標準の
disabled属性が付与されるため、必要に応じてCSSで「無効時は透明度を下げる」などの装飾をすれば、よりユーザーに伝わりやすくなります。
比較:手動JSでの制御 vs hx-disabled-elt
JavaScriptでの「ボタン保護」
const btn = document.querySelector('#save-btn');
btn.addEventListener('click', async () => {
btn.disabled = true; // 止める
try {
await someApiCall();
} finally {
btn.disabled = false; // 戻す
}
});
try...finally を書かなければならず、コードが非常に複雑になります。
HTMXの hx-disabled-elt
HTMXが通信の成功・失敗を問わず、最後には必ず元の状態に責任を持って戻してくれます。あなたは何も心配する必要はありません。まとめ:初心者のための「安心感」の作り方
hx-disabled-elt は、ユーザーの不安を解消し、システムの安全性を守る「最高のガードマン」です。
- 「this」は魔法の言葉: 迷ったら、すべてのボタンに
hx-disabled-elt="this"を付けておいても良いくらい、非常に汎用性の高いテクニックです。 - 視覚的なフィードバックを: ボタンが押せなくなる(グレーアウトする)ことは、ユーザーに「今、処理中だよ」と伝える重要なサインになります。
- サーバーの負担軽減: 無駄な連打を減らすことは、結果的にサーバーを救い、アプリ全体の速度向上にも繋がります。
落ち着いて待ってもらうための、優しい工夫。hx-disabled-elt というガードマンを味方につけて、洗練された「失敗しない」Webアプリを構築してください。次の記事では、待っている間をさらに楽しく(あるいは分かりやすく)するための「hx-indicator」(035. hx-indicator)をご紹介します。