useSpreadSheetTable
useSpreadSheetTable はテーブルの状態を管理する TableInstance を返すフックです。
import { useSpreadSheetTable } from '@heynow-jp/react-spread-sheet-table'
const table = useSpreadSheetTable<Row>({ columns, initialData: data, rowKey: 'id',})Options
Section titled “Options”| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
columns | ColumnDef<T>[] | (必須) | カラム定義の配列 |
initialData | T[] | (必須) | 初期データ |
rowKey | keyof T | (必須) | 行のユニークキー |
onChange | (rows: ChangeInfo<T>[]) => void | - | 編集基準から変更された行を通知 |
onRowChangeCommitted | (commit: RowChangeCommit<T>) => void | - | 今回の操作で確定した変更前後の行を通知 |
onReorder | (rows: T[]) => void | - | 行並び替え時のコールバック |
validate | (value, row, key) => ValidationResult | null | - | カスタムバリデーション |
onValidationError | (errors) => void | - | バリデーションエラーのコールバック |
processRowChange | (candidate, previous, context) => ProcessRowChangeResult<T> | - | 行変更を確定前に補正または拒否 |
onRowChangeRejected | (rejection: RowChangeRejection<T>) => void | - | 拒否された操作と行を通知 |
readOnly | boolean | false | テーブル全体を読み取り専用に |
sortable | boolean | true | ソート有効/無効 |
filterable | boolean | true | フィルター有効/無効 |
reorderable | boolean | false | 行の並び替え有効/無効 |
resizable | boolean | true | 列リサイズ有効/無効 |
frozenColumns | number | 0 | 左から固定する列数(行番号列は常に固定) |
Return: TableInstance
Section titled “Return: TableInstance”| プロパティ/メソッド | 型 | 説明 |
|---|---|---|
data | T[] | 現在のデータ (フィルタ・ソート適用後) |
isDirty | boolean | 未保存の変更があるか |
canUndo | boolean | Undo 可能か |
canRedo | boolean | Redo 可能か |
undo() | () => void | 操作を元に戻す |
redo() | () => void | 操作をやり直す |
resetToInitial() | () => void | 初期データにリセット |
replaceData(rows) | (rows: T[]) => void | 新しい行データへ差し替え、変更履歴を初期化 |
markAsSaved() | () => void | 現在のデータを保存済みとしてマーク |
isValid() | () => boolean | バリデーションエラーがないか |
getValidationErrors() | () => ValidationError[] | バリデーションエラー一覧 |
getChangedRows() | () => ChangeSet<T> | 変更された行の差分 |
frozenColumns | number | 固定列数 |
行変更を確定前に処理する
Section titled “行変更を確定前に処理する”processRowChangeを使うと、単一セル編集、ペースト、範囲のDelete・Cutのいずれでも、変更後の行を確定前に補正または拒否できます。
処理は同期関数として実装します。
const table = useSpreadSheetTable<ShiftRow>({ columns, initialData, rowKey: 'id', processRowChange: (candidate, _previous, context) => { const nextRow = context.changes.some((change) => change.key === 'startTime') ? { ...candidate, // 利用側の業務ロジックで終了時刻を補正する endTime: calculateEndTime(candidate.startTime), } : candidate
if (nextRow.startTime >= nextRow.endTime) { return { status: 'rejected', issues: [ { columnKey: 'endTime', result: { level: 'error', message: '終了時刻は開始時刻より後にしてください', }, }, ], } }
return { status: 'accepted', row: nextRow, } }, onRowChangeCommitted: (commit) => { for (const { previousRow, row } of commit.rows) { saveChangedRow(previousRow, row) } }, onRowChangeRejected: (rejection) => { console.log('Rejected row change:', rejection.rows) },})contextにはrowIndex、操作元を示すsource、確定前のchangesが含まれます。
sourceは単一セル編集がedit、ペーストがpaste、DeleteとCutによるクリアがclearです。
補正した値は元の編集と同じ操作として記録されるため、1回のUndoでまとめて元に戻ります。
複数行のペーストでは、1行でも拒否されるとペースト全体を反映しません。
範囲を選択したDeleteとCutも同じ扱いで、1行でも拒否されると範囲全体をクリアしません。
onChangeは編集基準からの累積変更を通知します。
今回の操作だけをAPIへ送る場合は、onRowChangeCommittedのpreviousRowとrowを使用してください。
渡された行はテーブル内のスナップショットとして読み取り専用で扱います。