Table
Table is a data-bound table component rendered as an HTML <table> element. It composes a header, a virtual-scrolling body, and an optional footer, all wired to an AbstractStore.
When no ColumnSpec is supplied, the table auto-generates one column per model field with default sizing.
Quickest example
import { Model, MemoryStore } from '@jimka/typescript-ui/data';
import { Table } from '@jimka/typescript-ui/component/table';
const PersonModel = new Model([
{ name: 'id', type: 'number' },
{ name: 'name', type: 'string' },
{ name: 'age', type: 'number' },
]);
const store = new MemoryStore(PersonModel, [
{ id: 1, name: 'Alice', age: 30 },
{ id: 2, name: 'Bob', age: 25 },
]);
await store.load();
const table = Table(store);
panel.addComponent(table);Constraining columns
Pass a ColumnSpec to control which columns appear, their widths, and visibility:
import { Table } from '@jimka/typescript-ui/component/table';
const table = Table(store, {
columns: [
{ field: 'name', minWidth: 120 },
{ field: 'age', maxWidth: 80, hidden: true },
],
appendUnlisted: false, // skip auto-generated columns for fields not listed
});ColumnConfig field | Purpose |
|---|---|
field | Model field name presented in this column. |
minWidth / maxWidth | Width constraints in pixels. |
hidden | Initial hidden state. |
showSeconds | For time / datetime columns: include seconds. |
appendUnlisted (default true) controls whether fields not in the columns array are auto-generated after the listed ones.
Sorting and selection
- Click a column header to cycle through sort directions: ascending → descending → no sort.
- Shift-click a column header to compose a multi-column sort: each shift-click appends or toggles that column inside the current sort list (asc → desc → removed). When more than one column is active, a small priority badge (
2,3, …) is shown on each non-primary column header. - Drag a column header's right edge to resize.
- Right-click a column header to toggle column visibility via a context menu.
table.getSelectedRecord()/getSelectedRecords()return the user's selection.
Common methods
| Method | Purpose |
|---|---|
getStore() / setStore(store) | Read / replace the bound store. |
getSelectedRecord() / getSelectedRecords() | Current selection. |
setColumnVisible(field, boolean) | Show / hide a column. |
setColumnWidths(widths[]) | Set all column widths at once. |
setHeaderVisible(boolean) / setBodyVisible(boolean) / setFooterVisible(boolean) | Toggle structural sections. |
exportCSV(options?) / exportJSON(options?) | Trigger a download of the current store view. |
setExportMenuEnabled(boolean) | Adds "Export as CSV" / "Export as JSON" entries to the column context menu. |
Exporting
exportCSV() and exportJSON() serialize the current store view — the same filtered, sorted records the user sees — and trigger a browser download. By default only visible columns are included; pass { includeHidden: true } to include columns hidden by the user or by the spec's hidden flag.
table.exportCSV(); // visible columns → table-export.csv
table.exportJSON({ filename: 'people.json' }); // visible columns, custom filename
table.exportCSV({ includeHidden: true }); // every resolved columnTo surface export from the column context menu, opt in:
table.setExportMenuEnabled(true);CSV output follows RFC 4180: fields containing ,, ", or \n are wrapped in double quotes and interior quotes are doubled. Null and undefined cell values serialize as the empty string (CSV) or null (JSON).
Date, time, and datetime cells are formatted with the same toLocaleDateString / toLocaleTimeString / toLocaleString options the cell renderers use, so exports match what the user sees — including the showSeconds setting from the column spec.
TablePanel exposes the same three methods (setExportMenuEnabled, exportCSV, exportJSON) as delegates to its inner Table.
Performance
The body uses virtual scrolling: only rows visible in the viewport plus a small buffer are in the DOM at any time. A pool of reusable row components is rebound (not recreated) as the user scrolls. Scrolling itself is JS-owned via a VirtualScroller — translate3d transform plus two custom Scrollbar overlays — with wheel, touch (fling momentum), and keyboard navigation funnelled through the same setScrollY / setScrollX entry points. See Body for the implementation.
Horizontal scrolling kicks in automatically when the combined column width exceeds the table's width.
For large datasets, AbstractStore automatically offloads sort and filter operations to a Web Worker once the dataset exceeds 1,000 rows.
See also
- API: Table
- API: ColumnSpec, ColumnConfig, ExportOptions
TablePanel— table + add/remove/sync toolbar- Data layer — Model, Store, Proxy, Binding
- Recipe: CRUD with a Table