コンテンツにスキップ

データグリッドの編集競合

2 人が同じ行を編集したとき、後から保存した側が黙って勝ってはいけません。 このレシピは datagrid-edit-errors のレコードレイアウトに楽観的ロックを足します: レコード tbody が data-version を持ち、PATCH がそれを同送し、古いバージョンは 409 で応答します — レコードは競合プレゼンテーションとして 再描画されます: セルにはサーバーの現在値(data-attention="error")、 新しいバージョン、そして両方の値を名指しするアラートに 上書き / 破棄 のアクション。モーダルもクライアント側マージ UI もありません: 行そのものがマージ UI です。 バージョニングポリシーの 対象です。

別名: 楽観ロック、排他制御。

Price を編集(ダブルクリック、またはセルで Enter)して 任意の数値をコミットしてください — デモは他のユーザーがすでに 20.00 を保存した状況をシミュレートするため、最初のコミットは必ず 競合します: 相手の値がセルに入り、アラートがあなたの値での上書き (バージョンが新しくなっているので成功します)か破棄を提案します。

NamePrice
Chai18.00
<!-- .hc-datagrid ラッパーの中 — このテンプレートがなければ何も
編集可能にならず、hc:datagridedit は発火しません: -->
<template data-datagrid-editor data-col="price">
<input class="hc-input" type="text" inputmode="decimal" aria-label="Price">
</template>
<tbody class="hc-datagrid__record" id="item-1" data-version="3"
data-hx-patch="/items/1"
data-hx-trigger="hc:datagridedit"
data-hx-vals="js:{ col: event.detail.col, value: event.detail.value,
version: event.target.closest('tbody').dataset.version }"
data-hx-disinherit="hx-vals"
data-hx-swap="outerHTML">
<tr class="hc-datagrid__row">
<td class="hc-datagrid__cell">Chai</td>
<td class="hc-datagrid__cell" data-numeric data-editable
data-col="price" data-value="18">18.00</td>
</tr>
</tbody>

hc:datagridedit は編集されたセルからバブリングするため、 event.target.closest('tbody') がレコードを解決し、現在のバージョンが 同乗します。 field-errors 契約が 422 用に文書化している一度きりの htmx:beforeSwap 許可に 409 を 足してください。

PATCH /items/:id(colvalueversion):

ケースレスポンス
バージョン一致・受理200 + レコード — サーバーの整形、インクリメントされた data-version
バージョン一致・拒否422datagrid-edit-errors のブランチ(バージョンは維持)
古いバージョン409 + 競合プレゼンテーション: セルには相手の値 + data-attention="error"新しい data-version、両方の値を名指しする role="alert" の競合行に、上書きボタン(静的 data-hx-vals であなたの値を新バージョンに対して再送)と破棄ボタン(行の data-hx-get)
未知の行 / 列404 — 標準のエラートーストがカバー

GET /items/:id はレコードを素のまま返します — 破棄のターゲット です。上書きでの再競合は、より新しい値で再提示されるだけです。 上書きは明示的な同意による last-writer-wins です。

プログレッシブエンハンスメント

Section titled “プログレッシブエンハンスメント”

楽観的ロックは編集そのものと一緒にデグレードします。no-JS の経路は edit-conflict レシピのフルフォーム 409 ページです。

  • 競合は role="alert" で読み上げられ、両方の解決はメッセージセル内の 本物のボタンです。
  • data-attention="error" が行を視覚的にマークし、かつメッセージが値を 名指しします — 決して色だけではありません。
  • どちらの解決でもレコードはその場で再描画され、キーボードユーザーは そこから続行できます。
  • datagrid-edit-errors — このレシピがバージョンで拡張する 422 の兄弟。
  • edit-conflict — フォーム全体のための同じ 409 哲学。
  • sse-updates — ライブ行リフレッシュは競合を減らします。すり抜けたレースをこの 契約が受け止めます。