# ClientVirtualTable V2 — Server Fetching Guide This guide focuses on `fetchMode="server"` usage (Tabs 2, 2-B, 3 in `/[lng]/test/table-v2`). Client mode is unchanged from `GUIDE.md`. ## Core Concepts - `fetchMode="server"` sets `manualPagination|manualSorting|manualFiltering|manualGrouping` to true. The table **renders what the server returns**; no client-side sorting/filtering/pagination is applied. - You must control table state (pagination, sorting, filters, grouping, globalFilter) in the parent and refetch on change. - Provide `rowCount` (and optionally `pageCount`) so the pagination footer is accurate. - Export uses the current row model; in server mode it only exports the loaded page unless you fetch everything yourself. ## Minimal Wiring (Factory Service) ```tsx const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [globalFilter, setGlobalFilter] = useState(""); const [data, setData] = useState([]); const [rowCount, setRowCount] = useState(0); const [loading, setLoading] = useState(false); useEffect(() => { const run = async () => { setLoading(true); const res = await getTableData({ pagination, sorting, columnFilters, globalFilter, }); setData(res.data); setRowCount(res.totalRows); setLoading(false); }; run(); }, [pagination, sorting, columnFilters, globalFilter]); ``` ## Using `createTableService` (Pattern 2) - Import `createTableService` in a server action and pass `columns` (accessorKey-based) plus schema/db. - The adapter maps `sorting`, `columnFilters`, `globalFilter`, `pagination` to Drizzle query parts. - Returned shape: `{ data, totalRows, pageCount }`. Always forward `totalRows` to the client. ## Custom Service (Pattern 3) - Build custom joins manually; still read `tableState` for pagination/sorting/filtering if you need them. - For sorting: map `tableState.sorting` IDs to your joined columns; provide a default order if none is set. - Grouping in custom services requires manual implementation (see `getOrderTableDataGroupedByStatus` pattern). ## Server Grouping (Pattern 2-B) - Only columns marked `meta.serverGroupable` in server column defs should be used. - Group headers are fetched via DB `GROUP BY`; expanded rows are fetched per group. - When grouping is active, the table may render a custom grouped view instead of the virtual table; ensure your fetcher returns either `{ groups }` or `{ data, totalRows }`. ## Presets in Server Mode - Presets store: sorting, columnFilters, globalFilter, columnVisibility, columnPinning, columnOrder, grouping, pageSize. - Loading a preset triggers the table’s `set*` APIs; parent `on*Change` handlers refetch with the restored state. - The component resets pageIndex to 0 when applying a preset to avoid out-of-range requests after pageSize changes. - Use unique `tableKey` per screen to avoid clashing presets across pages. ## Common Pitfalls - Forgetting `rowCount` → pagination shows wrong totals. - Not reacting to `sorting`/`filters`/`grouping` changes in your effect → UI toggles with no data change. - Mapping `sorting` IDs to columns incorrectly in custom services → server ignores the sort. - Mixing client-side models with server mode: do not enable client `getSortedRowModel`/`getFilteredRowModel` for server fetches (the component already skips them when `fetchMode="server"`). ## Feature Matrix (Server Mode) - Sorting: Supported; must be implemented in the server fetcher. - Filtering: Supported; column filters/global filter forwarded; implement in server. - Pagination: Supported; manual; provide `rowCount`. - Grouping: Client grouping is off in server mode; implement via server `GROUP BY` or custom grouped view. - Column show/hide, pinning, reorder: Client-side only; state is preserved and sent to presets but does not affect server queries unless you opt to read it. - Export: Exports the currently loaded rows; fetch all data yourself for full exports. ## Debug Checklist - Confirm `fetchMode="server"` and `rowCount` are set. - Verify the parent effect depends on `pagination`, `sorting`, `columnFilters`, `globalFilter`, and (if used) `grouping`. - In custom services, console/log the incoming `tableState` to confirm the UI is sending the intended state.