未保存ガード
入力途中のフォームを失うことは、業務アプリで最も多い苦情の類型です。
data-hc-dirty-guard(自動インストールされる installDirtyGuard())は
フォームを編集状態について正直にします: 最初の実変更で data-dirty が
現れ、タブは黙って閉じなくなり、boosted ナビゲーションは先に確認し、
保存が成功すればベースラインがリセットされます。クライアント専用 —
保存自体はフォームが既に従っている契約のままです。
バージョニングポリシーの
対象です。
別名: 離脱ガード、ダーティチェック、未保存警告。
プレビューは動いています: タイトルを編集するとバッジが現れます
(素の form[data-dirty] CSS フック)。元の文字列に戻すと消えます。
ダーティなままタブを閉じようとすると警告されます — このデモの
フォームにはサーバーがないため、Save は何もしません。
<form data-hc-dirty-guard data-hx-post="/reports/42" data-hx-target="#status" data-hx-swap="innerHTML"> <div class="hc-field"> <label class="hc-field__label" for="title">Title</label> <input class="hc-input" id="title" name="title" value="Quarterly report"> </div> <p class="hc-field__hint" id="status" aria-live="polite"></p> <button class="hc-button" data-variant="primary" type="submit">Save</button></form>ガードがすること
Section titled “ガードがすること”| タイミング | 効果 |
|---|---|
| フォーム内で最初のフォーカス | ベースラインのスナップショット(new FormData(form) 経由 — installFormat の正準値なので、表示上の再グループ化が「ダーティ」になることはありません) |
任意の input / change | 比較 → data-dirty をトグルし、反転時に hc:dirtychange { dirty } をディスパッチ |
| ダーティなままタブを閉じる / リロード | ブラウザの汎用プロンプト(現代のブラウザはカスタム文字列を無視します) |
ダーティな状態での boosted <a> ナビゲーション | dirtyguard.leave メッセージでの window.confirm(setMessages() でローカライズ) |
| フォーム自身のリクエストが成功 | 再スナップショット → クリーン |
| フォーム内発だがフォーム自身ではないリクエスト | クリーンになりません — autosave のドラフトはドラフトのまま |
| ネイティブ送信 | 決して警告しません(submit は制約検証を通過した後にだけ発火します) |
状態のスタイリング
Section titled “状態のスタイリング”data-dirty はただの属性です — アプリの CSS でスタイルします:
.unsaved-badge { visibility: hidden; }form[data-dirty] .unsaved-badge { visibility: visible; }サーバーが data-dirty をレンダリングしても構いません(復元
されたドラフトは定義上未保存です) — ガードは属性だけから警告します。
プログレッシブエンハンスメント
Section titled “プログレッシブエンハンスメント”JavaScript がなければ何も守りませんが、何も壊れません: フォームは ネイティブに送信されます。構造からして純粋なエンハンスメントです。
アクセシビリティ
Section titled “アクセシビリティ”- タブを閉じる際のプロンプトはブラウザ自身のダイアログです。
- 視覚的なバッジだけで足りないときは、
hc:dirtychangeで状態をaria-liveのステータス行に写してください。
- autosave — 入力と 同時にドラフトを保存し、警告の出番をほぼなくします。
- mutating-form — ガード付きフォームが通常従う保存契約。