🥸

htmx + mustache + oakで簡単なAPI描画

2023/06/18に公開
  • html内の任意の属性を指定することで、jsの記述無しでインタラクティブなサイトを作成できるhtmxという技術を試しています。
  • あらゆるイベントをトリガーにしたAjax通信を短い記法で簡単に実現することができます。
  • 今回はJSONを返すAPIをhtmxで扱い、テンプレートエンジンのmustacheで描画する方法を記録いたします。

環境

  • macOS 13.0
  • deno 1.34.2

手順

APIの作成

  • 対象のAPIを簡単に作成するため、denoのoakを利用します。
  • まず任意のフォルダにtsファイルを作成します。
mkdir ~/htmx-oak
cd ~/htmx-oak
touch app.ts
  • 作成したtypescriptファイルを以下の内容にします。
import { Application, Router } from "https://deno.land/x/oak@v12.5.0/mod.ts";
import { getQuery } from "https://deno.land/x/oak@v12.5.0/helpers.ts";

const app = new Application();
const router = new Router();

app.use(router.routes());
app.use(router.allowedMethods());

router
  .get("/", async (ctx) => {
    ctx.request.url.pathname = "index.html";
    await ctx.send({
      root: Deno.cwd(),
    });
  })
  .get("/api/users", (ctx) => {
    const users = [
      {
        id: 1,
        name: "tanaka",
      },
      {
        id: 2,
        name: "suzuki",
      },
      {
        id: 3,
        name: "sasaki",
      },
      {
        id: 4,
        name: "takahashi",
      },
    ];

    // クエリパラメータ取得
    const params = getQuery(ctx);
    const search = params.search;

    // なければそのまま返す。
    if (!search) {
      ctx.response.body = users;
      return;
    }

    // クエリパラメータの値でフィルタリングして返す。
    ctx.response.body = users.filter((user) => {
      return user.name.includes(search);
    });
  });

await app.listen({ port: 8000 });
  • 記述後、以下のコマンドを実行してアプリサーバーを起動してください。
deno run --allow-net --allow-read app.ts
  • localhost:8000/api/usersにアクセスして、以下のレスポンスになっていて、簡易的なUser APIが作成できていることを確認します。
[
  {
    "id": 1,
    "name": "tanaka",
  },
  {
    "id": 2,
    "name": "suzuki",
  },
  {
    "id": 3,
    "name": "sasaki",
  },
  {
    "id": 4,
    "name": "takahashi",
  },
]

htmxの用意

  • APIが用意できたので、そのレスポンスを描画するためのHTMLファイルを以下で作成します。
touch index.html
  • 作成したhtmlの内容を以下にします。
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>try-htmx</title>
  <script src="https://unpkg.com/htmx.org"></script>
  <script src="https://unpkg.com/htmx.org/dist/ext/client-side-templates.js"></script>
  <script src="https://unpkg.com/mustache@latest"></script>
</head>

<body>
  <div hx-ext="client-side-templates">
    <input type="search" name="search" hx-get="/api/users" hx-swap="innerHTML" hx-target="#content"
      mustache-template="users" hx-trigger="load, keyup changed delay:500ms, search">
    <div id="content"></div>
    <template id="users">
      <ul>
        {{#.}}
        <li>{{id}} : {{name}}</li>
        {{/.}}
      </ul>
    </template>
  </div>
</body>

</html>
  • 上記の記述では以下のscriptをheadタグで読み込んでいます。

  • また属性とそれに対する動作としては以下です。

    • hx-get : /api/usersにGETリクエスト。
    • hx-trigger : 「読み込み・入力後の500ms後」にhx-getを発火。
    • hx-swap : レスポンスの描画。
    • hx-target : 描画先の要素。
  • 再度deno run --allow-net app.tsを実行して、上記の動作の流れになっていることを確認します。

image.png

image.png

  • 以上です。

まとめ

  • 簡易的な試用であったが、htmxを利用すればあらゆるイベントをトリガーにしたajax通信が簡単に実現可能。
  • 簡易的なものならhtmlファイルだけでまとまり、また動作の流れも上から追えるのも非常に便利。
  • より便利な機能もあるらしいので、継続的に調査する。

参考

Discussion