htmxで作るWebページをさらに進化させる:サンプルコードで理解を深める


hx-postの役割

  • サーバーからのレスポンスは、デフォルトでは要素のinnerHTMLに置き換えられますが、hx-swap属性で置換方法を詳細に制御することができます。
  • 送信されるデータは、要素内に含まれるフォームデータや、hx-init 属性で設定されたデータとなります。

hx-postの利点

  • htmxライブラリによる自動的なDOM操作により、レスポンスのHTMLをシームレスに挿入・更新することができます。
  • Ajaxによる複雑なコーディングを必要とせず、シンプルな属性でPOSTリクエストを実行できます。
  • ページ全体を再読み込みすることなく、特定の領域のみを更新できるので、ユーザーインターフェースの高速化とレスポンスの向上を実現できます。

hx-postの構文

<element hx-post="/url" [hx-init="data"] [hx-swap="swap-method"] [hx-target="target-element"]>
  </element>
  • [hx-target="target-element"]: レスポンスのHTMLを挿入・更新する要素を指定 (省略可。デフォルトは要素自身)
  • [hx-swap="swap-method"]: レスポンスのHTMLを要素に挿入・更新する方法を指定 (省略可)
    • inner: デフォルト。要素のinnerHTMLを置き換えます。
    • outer: 要素全体を置き換えます。
    • append: 要素の末尾に挿入します。
    • prepend: 要素の先頭に挿入します。
  • [hx-init="data"]: 送信されるデータオブジェクトを指定 (省略可)
  • /url: POSTリクエストを送信するURL
  • element: hx-post属性を付与するHTML要素

hx-postの例

この例では、ボタンをクリックすると、/submitへPOSTリクエストを送信し、レスポンスで受け取ったメッセージを#message要素内に表示します。

<button hx-post="/submit" hx-init="{ name: 'Taro', message: 'Hello!' }" hx-swap="inner" hx-target="#message">送信</button>


フォーム送信によるデータ更新

この例では、フォームを送信すると、入力された名前とメッセージをサーバへ送信し、更新されたメッセージリストをレスポンスとして受け取ります。その後、#messages要素内にリストを挿入します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>hx-postを使ったフォーム送信</title>
  <link rel="stylesheet" href="style.css">
  <script src="https://unpkg.com/[email protected]/dist/htmx.min.js"></script>
</head>
<body>
  <h1>メッセージ一覧</h1>

  <form hx-post="/messages" hx-swap="append">
    <label for="name">名前:</label>
    <input type="text" id="name" name="name">
    <br>
    <label for="message">メッセージ:</label>
    <textarea id="message" name="message"></textarea>
    <br>
    <button type="submit">送信</button>
  </form>

  <div id="messages"></div>

  <script>
    // サーバーからメッセージを受信した後に、成功メッセージを表示
    htmx.on('htmx:afterRequest', (event) => {
      if (event.target.status === 200) {
        alert('メッセージを送信しました!');
      }
    });
  </script>
</body>
</html>

ボタンクリックによる個別データ更新

この例では、ボタンをクリックすると、ボタンのIDとそれに対応するメッセージをサーバへ送信し、更新されたメッセージをレスポンスとして受け取ります。その後、#message-${id}要素内にメッセージを挿入します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>hx-postを使った個別データ更新</title>
  <link rel="stylesheet" href="style.css">
  <script src="https://unpkg.com/[email protected]/dist/htmx.min.js"></script>
</head>
<body>
  <h1>メッセージ一覧</h1>

  <ul>
    <li>
      <button hx-post="/messages/1" hx-init="{ id: 1, message: 'こんにちは!' }" hx-swap="inner" hx-target="#message-1">メッセージ1</button>
      <div id="message-1"></div>
    </li>
    <li>
      <button hx-post="/messages/2" hx-init="{ id: 2, message: 'ありがとう!' }" hx-swap="inner" hx-target="#message-2">メッセージ2</button>
      <div id="message-2"></div>
    </li>
  </ul>

  <script>
    // サーバーからメッセージを受信した後に、成功メッセージを表示
    htmx.on('htmx:afterRequest', (event) => {
      if (event.target.status === 200) {
        alert('メッセージを更新しました!');
      }
    });
  </script>
</body>
</html>

画像アップロードによるサムネイル表示

この例では、画像ファイルをアップロードすると、サーバへファイルを送り、アップロードされた画像のサムネイルをレスポンスとして受け取ります。その後、#thumbnail要素内にサムネイル画像を表示します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>hx-postを使った画像アップロード</title>
  <link rel="stylesheet" href="style.css">
  <script src="https://unpkg.com/[email protected]/dist/htmx.min.js"></script>
</head>
<body>
  <h1>画像アップロード</h1>

  <form hx-post="/upload" hx-swap="inner" hx-target="#thumbnail">
    <input type="file" name="image">
    <button type="submit">アップロード</button>
  </form>

  <div id="thumbnail"></div>

  <script>
    // サーバーから画像を受信した後に、成功メッセージを表示
    htmx.on('htmx:afterRequest', (event) => {
      if (event.target


JavaScript による Ajax リクエスト

  • 欠点:
    • コード量が増加: hx-post 属性よりもコード量が多くなります。
    • htmx の自動的な DOM 操作機能を利用できない: レスポンスのHTMLを挿入・更新する処理を自分で記述する必要があります。
  • 利点:
    • 高度なカスタマイズ性: 送信データ、ヘッダー、レスポンス処理などを詳細に制御できます。
    • 既存の JavaScript ライブラリとの連携が容易: jQuery や Axios などのライブラリを組み合わせて利用できます。

フォーム送信によるページ再読み込み

  • 欠点:
    • ユーザーインターフェースの非レスポンス: ページ全体が再読み込みされるため、ユーザーインターフェースが一時的に停止します。
    • SEOへの影響: ページ全体が再読み込みされるため、SEO に悪影響を与える可能性があります。
  • 利点:
    • シンプル: 特にデータ更新が単純な場合は、最もシンプルな方法です。

WebSockets による双方向通信

  • 欠点:
    • 複雑性: WebSockets の実装は複雑で、サーバ側の設定も必要です。
    • すべてのブラウザでサポートされているわけではない: 古いブラウザでは WebSockets をサポートしていない場合があります。
  • 利点:
    • リアルタイムな更新: サーバーとクライアント間でリアルタイムなデータのやり取りが可能で、常に最新の状態を維持できます。
  • 欠点:
    • 双方向通信には対応していない: サーバーからクライアントへ一方通行でのデータ送信のみ可能です。
    • 古いブラウザではサポートされているわけではない: 古いブラウザでは SSE をサポートしていない場合があります。
  • 利点:
    • リアルタイムな更新: WebSockets と同様に、サーバーからクライアントへリアルタイムにデータを送信できます。
    • WebSockets よりも軽量: WebSockets よりも実装がシンプルで、サーバ側の負荷も軽くなります。