状態と自作の操作部品
グリッドが表示するものはすべて 2 つのただの JSON から決まり、それを変えるのはすべてコマンドです。アプリは JSON を好きな場所に持ち、グリッドのメニューやキーと同じコマンドを送れます。
- ドキュメントは表示の設定です。プラン(計算列、条件、グループ、並べ替え)と列の設定(幅、非表示、固定、書式、合計)、それに
rowKeyを持ちます。利用者が保存したり、共有したり、エージェントに渡したりするものです。 - セッションは利用者がいる場所です。アクティブなセル、選択範囲、スクロールの位置、チェックした行、詳細パネル、開いている編集欄、元に戻す履歴を持ちます。
{ "kind": "vastgrid/document", "version": 2, "plan": { "where": { "fn": "eq", "args": [{ "col": "region" }, { "lit": "EU" }] }, "sort": [{ "column": "total", "direction": "desc" }] }, "columns": [{ "name": "id", "pin": "left" }, { "name": "total", "width": 120, "total": { "fn": "sum" } }]}すべてのメンバーは仕様の §5 にあります。型は GridDocument と GridSession で、vastgrid からエクスポートしています。
表示の設定を残す
Section titled “表示の設定を残す”グリッドに最初のドキュメントを渡し、グリッドが知らせるドキュメントを保存します。
import { DataGrid, type GridDocument } from "vastgrid";
function load(): GridDocument | undefined { const text = localStorage.getItem("orders-view"); return text ? (JSON.parse(text) as GridDocument) : undefined;}
export function Orders() { return ( <DataGrid transport={transport} table="orders" defaultDocument={load()} onDocumentChange={(document) => localStorage.setItem("orders-view", JSON.stringify(document))} /> );}defaultDocument を読むのは、グリッドがストアを作るときです。その後はグリッドがドキュメントを持ち、変わるたびに onDocumentChange を呼びます。保存した後に列が変わった表でドキュメントを開くと、ドキュメントは直されます。表に合わなくなった条件、グループ、並べ替えのキー、計算列を外し、残りはそのまま使います(§5.5)。
ドキュメントはバージョン 2 です。vastgrid 0.1 で保存した状態はそのままでは読めません。vastgrid-spec の migrateGridState でドキュメントにします(0.1 からの移行)。
表示の設定を制御する
Section titled “表示の設定を制御する”document を渡すと、グリッドはその prop を表示します。コマンドは作ったドキュメントを onDocumentChange に知らせ、それを渡し返すとグリッドが表示します。
const [document, setDocument] = useState<GridDocument>(initial);
<DataGrid transport={transport} table="orders" document={document} onDocumentChange={setDocument} />;- 別のものを渡し返せば、外から表示を変えられます。保存した表示、リンクの表示、エージェントが作った表示などです。何も渡し返さなければ、コマンドは効きません。
- 1 つのイベントの中の 2 つのコマンドは両方効きます。2 つ目は、1 つ目が知らせたドキュメントに対して働きます。
session、defaultSession、onSessionChangeも同じです。onSessionChangeはアクティブなセルが動くたびに呼ばれるので、セッションを状態に持つ親は、それで描き直す部分を小さくするか、useDeferredValueを通して読んでください。
自作の操作部品
Section titled “自作の操作部品”useCreateGridStore は、コンポーネントが生きている間のストアを作ります。グリッドには store で、自作のコンポーネントには GridProvider で渡します。その中では、useGridSelector で状態を読み、useGridDispatch で変えます。
import { DataGrid, GridProvider, useCreateGridStore, useGridDispatch, useGridSelector } from "vastgrid";
function Workbench() { const store = useCreateGridStore({ transport, table: "orders" }); return ( <GridProvider store={store}> <ClearSort /> <DataGrid store={store} toolbar={false} /> </GridProvider> );}
function ClearSort() { const sort = useGridSelector((snapshot) => snapshot.document.plan?.sort); const dispatch = useGridDispatch(); return ( <button type="button" disabled={!sort} onClick={() => dispatch({ command: "sort.clear" })}> 並べ替えを解除 </button> );}コマンドは、名前と引数を持つオブジェクトです。TypeScript が確かめます。
dispatch({ command: "sort.set", keys: [{ column: "total", direction: "desc" }] });dispatch({ command: "filter.column", column: "region", where: { fn: "eq", args: [{ col: "region" }, { lit: "EU" }] } });dispatch({ command: "column.pin", name: "id", side: "left" });dispatch({ command: "select", row: 0, column: "total" });dispatch はすぐに状態を変え、コマンドに必要なものをエンジンに送り、{ ok: true, output } か { ok: false, error } で解決します。reject はせず、失敗したコマンドは何も変えません。すべてのコマンドはコマンドにあります。
グリッド自身のコンポーネントと、DataGrid の中に描くコンポーネント(詳細パネル)は、プロバイダーなしで同じストアを読みます。外からは、ref でハンドル { store, dispatch, focus } を受け取れます。
スナップショットの中身
Section titled “スナップショットの中身”useGridSelector(selector) は、ストアのスナップショットに selector を適用します。スナップショットが書き換わることはありません。
| メンバー | 中身 |
|---|---|
document、session |
上の状態 |
table |
開いている表。ID、列、行数、リビジョン、読み込み中かどうか、エンジンの機能。開くまでは null |
view |
画面のビュー。行数、それが確定しているか、列、status("building" か "ready") |
displayed |
表示している列と設定を、表示の順で |
pending |
読んでいる途中のプラン。その間、前のビューは画面に残ります |
status |
"idle"、"opening"、"ready"、"error" |
error、failedWrite |
どのコマンドにも属さない最後の失敗と、最後に失敗した書き込み |
totals |
合計行の値。なければ null |
セレクターは軽くして、新しいオブジェクトを作らないでください。作るときは、それを比べる isEqual を渡します。useGridSelector((snapshot) => [snapshot.status, snapshot.view?.rowCount], shallowEqual) です。行はスナップショットに入っていません。useGridRows で読みます(グラフで使っています)。
React なしで
Section titled “React なしで”vastgrid/core には React を使わないストアがあります。ほかのフレームワークのホスト、テスト、サーバーで使えます。
import { createGridStore } from "vastgrid/core";
const store = createGridStore({ transport, table: "orders" });const disconnect = store.connect(); // 表を開いてビューを読むconst stop = store.subscribe(() => console.log(store.getSnapshot().view?.rowCount));
const outcome = await store.dispatch({ command: "search.set", text: "Tokyo" });
stop();disconnect(); // 表を閉じるストアを作るだけでは何も開きません。開くのは connect で、返す関数でまた表を閉じます。setDocument と setSession は外から渡した状態を表示します。ストアのほかのメソッドは vastgrid/core と vastgrid/server にあります。