🥸
htmx + mustache + oakで簡単なAPI描画
- 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タグで読み込んでいます。
- htmxの読み込み : CDN(unpkg)
- htmxのテンプレートエンジンサポート : CDN(unpkg)
- mustacheの読み込み : CDN(unpkg)
-
また属性とそれに対する動作としては以下です。
-
hx-get :
/api/users
にGETリクエスト。 - hx-trigger : 「読み込み・入力後の500ms後」にhx-getを発火。
- hx-swap : レスポンスの描画。
- hx-target : 描画先の要素。
-
hx-get :
-
再度
deno run --allow-net app.ts
を実行して、上記の動作の流れになっていることを確認します。
- 以上です。
まとめ
- 簡易的な試用であったが、htmxを利用すればあらゆるイベントをトリガーにしたajax通信が簡単に実現可能。
- 簡易的なものならhtmlファイルだけでまとまり、また動作の流れも上から追えるのも非常に便利。
- より便利な機能もあるらしいので、継続的に調査する。
Discussion