コンテンツにスキップ

レシピ

各レシピは、短縮形・展開後の HTML・任意のマクロ・サーバレスポンス契約を ドキュメント化しています。必要なもの列に記載のあるレシピは @hypermedia-components/coreの installX() を必要とします。それ以外(「—」)は純粋な htmx 属性だけです。

任意のレシピのスキャフォールドは npx @hypermedia-components/cli add <name> で取得できます。コピーは npx @hypermedia-components/cli validate で契約に対して機械検証できます。

各レシピページにはライブデモもあります。ほぼすべてのデモは、 このサイトの Worker が api/recipes/<name>/ 配下で実装する 各レシピのサーバ応答契約に対して、実際の htmx リクエストを送ります (例外: コピー、 条件付きフィールド、 未保存ガードは クライアントのみ、ストリーミング応答は chat-messages のエンドポイントを共有)。

フォームの構築と送信 — バリデーション、ウィザード、サーバ往復を 必要とする入力たち。

レシピ やりたいこと 必要なもの
ミューテーションフォーム インライン 4xx エラー・成功時リダイレクト・二重送信ガードつきでフォームを送信する installFieldErrors()
フィールドエラー サーバが送るバリデーションエラーフラグメントを、名前の一致するフィールドへ振り分ける installFieldErrors()
条件付きフィールド 選択中のモードが読まないフィールドを、往復なしで宣言的に隠す installShowWhen()
マルチステップフォーム ウィザードを作る — ステップとドラフトはサーバが所有し、ステップ全体をスワップ —
インライン編集 値を表示モードと編集モードの間でその場でスワップする(クリックして編集) —
ファイルアップロード ライブ進捗バーと out-of-band フォームリセットつきでマルチパートアップロードする installUploadProgress()
郵便番号住所補完 郵便番号から住所を補完したい — マスク付き入力、1 回のルックアップ GET、アウトオブバンドの自動入力 installMask()
マスタ参照 マスタを参照する — change で検証されるコード直接入力+検索ダイアログのピッカー。未解決コードは hidden の id を必ずクリア installRemoteDialog() + installCloseDialog()
カスケードセレクト 階層選択を連鎖する(依存)select で行う — change のたびに次のレベルを読み込み —
トランスファー デュアルリストボックスの割り当て / 解除をサーバ往復で行う — フォーム全体のスワップ、カスタム JS ゼロ —

作業中の内容を守る — ドラフト、ダーティ状態、セッション切れ、 落ちた接続、そして競合・重複する保存。

レシピ やりたいこと 必要なもの
未保存ガード 編集が失われる前に警告したい — data-dirty 状態、タブを閉じる際のプロンプト、boosted ナビの確認、保存でクリーン installDirtyGuard()
自動保存 入力と同時にフォームをドラフトしたい — デバウンス送信、復元バナー、新規 JS ゼロ —
編集競合 楽観ロックにしたい — 隠し version が毎回の保存に同乗し、古い保存は 409 の競合ダイアログに —
冪等キー 二重送信をサーバ側で無害化する — 描画フォームごとにキー 1 つ。リプレイには元のレスポンスを返し、エラーにしない —
セッション切れ再認証 401 をログインダイアログにして、中断されたリクエストを再実行したい installSessionExpiry()
ネットワーク再試行 応答がまったく来なかったリクエスト(オフライン / タイムアウト)を、動く Retry 付きで表面化する installNetworkRetry()

要素ひとつ、リクエストひとつ — ボタン、ガード、小さな クライアントサイドユーティリティ。

レシピ やりたいこと 必要なもの
リクエストアクション ビジー状態つきのボタンから htmx リクエストを発行する —
確認アクション 破壊的リクエストを確認ダイアログでガードする installConfirm()
削除の取り消し 即座に削除する(楽観的削除)— 猶予期間内ならトーストの Undo で行を復元 installToast()
クリップボードにコピー 読み取り専用の値(URL、トークン、スニペット)をクリップボードへコピーする installCopy()
並べ替えリスト サーバが順序を所有するリストをポインタ/キーボードで並べ替え、リクエスト 1 本で永続化する installSortable()

業務レコードが通る契約 — 明細行、ライフサイクル、一括投入、 長時間処理。

レシピ やりたいこと 必要なもの
明細行 受注・見積の明細行を編集する — 追加・削除・再計算はフォーム全体の往復。計算はすべてサーバが所有 —
ワークフローアクション レコードのライフサイクルを駆動する — サーバは合法な遷移だけを描画。コメント必須の遷移は 422、陳腐化した操作は現在の真実で 409 —
CSV インポート 驚きなしの一括投入 — アップロード、検証レポート、トークン付き確定 —
非同期ジョブ リクエストより長生きする処理を回す — 202 + 終端状態を列挙した自己ポーリングのジョブカード —

hc-datagrid コンポーネントを運用するためのすべて — ページング、ソート / フィルタ / 列のツーリング、インライン編集のエラーワイヤ、そして大きなグリッドを 正直に保つパターン。データグリッドページ テンプレートが、これらすべてが載るレイアウトを組み立てます。 初めてなら、全体を構築順で地図化した データグリッドガイドから 始めてください。

レシピ やりたいこと 必要なもの
データグリッドのページネーション データグリッドをサーバ駆動でページングする — out-of-band の行スワップつき installDatagrid()
データグリッドの並び替え 適用中のソート集合を述べ、その場で編集させたい — 並べ替え可能な順序付きリスト。表示していない列のキーも扱える installSortList()
データグリッドの列フィルタ 列ごとのフィルタポップオーバー — 名前空間付き f-col パラメータでグリッドを GET し、トリガーが data-filtered で戻る —
データグリッドの列選択 ユーザーごとにグリッドの列を選ばせたい — チューザーフォームが cols= の繰り返しパラメータ付きでグリッドを GET —
データグリッドの列プリファレンス ユーザーごとの列幅・列順を記憶 — ミラー入力がリサイズをオートセーブ。ソータブルなチューザーの cols= 順が列順 —
行から詳細へ 行が指すレコードを開いて同じ一覧に戻る — 同一性の列のリンク、戻りの #row-<id>、結果セットや選択を辿る installRowLink()
データグリッドのツリー グリッド内の階層 — aria-level の行が子を親の直後に遅延ロード —
データグリッド無限スクロール ページ番号なしの無限リスト — revealed の番兵行が次のカーソルバッチをスワップ —
データグリッドのスナップショットページャー ワークキューの母集合を検索時点で凍結する — フォームが行キーを運び、処理済み行は見え続け、消えた行はトゥームストーンに installDatagrid()
データグリッドの編集エラー グリッドの楽観的コミットのループを閉じる — 422 がマーク付きセル+エラー行つきでレコードを再描画 —
データグリッドの編集競合 行単位の楽観的ロック — 古いバージョンは 409 で上書き/破棄つきの競合行へ —
データグリッド一括操作 チェックボックスで行を選択し、1 つのアクションを全行に POST する installDatagridActions()
データグリッドの一括操作エラー 大量エラーの一括操作 — best-effort と atomic、理由別集約、レポートから行へのリンク —
レシピ やりたいこと 必要なもの
ライブ検索 入力に応じて検索する(タイプアヘッド)— デバウンスされた入力で結果をスワップ —
検索結果の上限 1 回の検索が返せる件数を制限する — cap+1 検出、「cap+」件数、残り続ける切り詰めバナーまたはハードリジェクト —
フィルタポップオーバー フィルタフォームをポップオーバーに載せ、成功時に閉じる installClosePopover()
保存ビュー 現在のフィルタに名前を付けて、ただのリンクとして呼び戻したい — サーバー保存のクエリ文字列 —
レシピ やりたいこと 必要なもの
レイジーパネル パネルの読み込みを、初めて表示されるまで遅延する —
レイジーツリー ツリーの枝の子を初回展開時に読み込む installTree()
データ領域 HX-Trigger の無効化を起点に領域を自己更新する —
レシピ やりたいこと 必要なもの
SSE 更新 Server-Sent Events でサーバからフラグメント更新をプッシュする — 名前付きイベントと out-of-band プッシュ —
SSE トースト JSON ペイロードつき SSE イベントを許可リスト方式の DOM イベントへ変換する — トーストはそのまま動作 installSseDispatch()
チャットメッセージ コンポーザーの 1 POST でチャットのやり取り(ユーザーメッセージ + aria-busy のアシスタントプレースホルダー)を追記。422 経路はトランスクリプトを汚しません installChatScroll()
ストリーミングレスポンス アシスタントのプレースホルダーを SSE で埋める — aria-busy が読み上げを保留する間チャンクを追記し、done が最終メッセージに置換してストリームを閉じます —
レシピ やりたいこと 必要なもの
リモートダイアログ ダイアログ(モーダル)の中身を、開くときにサーバから読み込む installRemoteDialog() + installCloseDialog()
トースト クライアントまたは HX-Trigger ヘッダーからトースト通知(スナックバー)を発火する installToast()
未読バッジ アプリクロームの通知カウントを新鮮に保ち、ゼロでは正直に消し、自分の操作で即時補正する —
レシピ やりたいこと 必要なもの
チャート サーバが送るデータテーブルを Observable Plot の SVG チャートへ昇格する installChart() + Plot