4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

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

Posted at
  • 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ファイルだけでまとまり、また動作の流れも上から追えるのも非常に便利。
  • より便利な機能もあるらしいので、継続的に調査する。

参考

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?