TableViewModel

TableViewModel describes the structure of the table. Everything you render reads from vm.current: plain reactive values backed by $derived, so a template that reads them updates when the data or any plugin state changes.

const vm = table.createViewModel(columns)
// vm.current.headerRows, vm.current.pageRows, vm.current.tableAttrs, ...
// vm.flatColumns, vm.pluginStates, vm._debug
const vm = table.createViewModel(columns)
// vm.current.headerRows, vm.current.pageRows, vm.current.tableAttrs, ...
// vm.flatColumns, vm.pluginStates, vm._debug
Information:
v7 removed the store fields (vm.rows, vm.headerRows, ...). Subscribe was removed in v7; see Migrating to v7.

Usage

TableViewModel#current: ViewModelCurrent

The reactive values of the table: tableAttrs, tableHeadAttrs, tableBodyAttrs, visibleColumns, headerRows, originalRows, rows and pageRows. Combined with row.current and cell.current, that is the whole rendering surface:

<table {...vm.current.tableAttrs}>
    <thead {...vm.current.tableHeadAttrs}>
        {#each vm.current.headerRows as headerRow (headerRow.id)}
            <tr {...headerRow.current.attrs}>
                {#each headerRow.cells as cell (cell.id)}
                    <th {...cell.current.attrs}><Render of={cell.render()} /></th>
                {/each}
            </tr>
        {/each}
    </thead>
    <tbody {...vm.current.tableBodyAttrs}>
        {#each vm.current.pageRows as row (row.id)}
            <tr {...row.current.attrs}>
                {#each row.cells as cell (cell.id)}
                    <td {...cell.current.attrs}><Render of={cell.render()} /></td>
                {/each}
            </tr>
        {/each}
    </tbody>
</table>
<table {...vm.current.tableAttrs}>
    <thead {...vm.current.tableHeadAttrs}>
        {#each vm.current.headerRows as headerRow (headerRow.id)}
            <tr {...headerRow.current.attrs}>
                {#each headerRow.cells as cell (cell.id)}
                    <th {...cell.current.attrs}><Render of={cell.render()} /></th>
                {/each}
            </tr>
        {/each}
    </thead>
    <tbody {...vm.current.tableBodyAttrs}>
        {#each vm.current.pageRows as row (row.id)}
            <tr {...row.current.attrs}>
                {#each row.cells as cell (cell.id)}
                    <td {...cell.current.attrs}><Render of={cell.render()} /></td>
                {/each}
            </tr>
        {/each}
    </tbody>
</table>

A read inside a template, $derived or $effect is tracked. A read anywhere else (a load function, a test, server rendering) returns the current value.

Attributes

TableViewModel#current.tableAttrs: TableAttributes

Attributes to spread onto the <table> element.

TableViewModel#current.tableHeadAttrs: TableHeadAttributes

Attributes to spread onto the <thead> element.

TableViewModel#current.tableBodyAttrs: TableBodyAttributes

Attributes to spread onto the <tbody> element.

Rows

TableViewModel#current.headerRows: HeaderRow[]

The HeaderRows that represent <tr> elements in <thead>.

<thead>
    {#each vm.current.headerRows as headerRow (headerRow.id)}
        <tr {...headerRow.current.attrs}>...</tr>
    {/each}
</thead>
<thead>
    {#each vm.current.headerRows as headerRow (headerRow.id)}
        <tr {...headerRow.current.attrs}>...</tr>
    {/each}
</thead>

TableViewModel#current.rows: BodyRow[]

The BodyRows that represent <tr> elements in <tbody>, after every plugin’s row transformation.

<tbody>
    {#each vm.current.rows as row (row.id)}
        <tr {...row.current.attrs}>...</tr>
    {/each}
</tbody>
<tbody>
    {#each vm.current.rows as row (row.id)}
        <tr {...row.current.attrs}>...</tr>
    {/each}
</tbody>

TableViewModel#current.pageRows: BodyRow[]

The BodyRows of the current page.

current.pageRows is affected by pagination plugins while current.rows is not. Without a pagination plugin the two are equal.

<tbody>
    {#each vm.current.pageRows as row (row.id)}
        <tr {...row.current.attrs}>...</tr>
    {/each}
</tbody>
<tbody>
    {#each vm.current.pageRows as row (row.id)}
        <tr {...row.current.attrs}>...</tr>
    {/each}
</tbody>

TableViewModel#current.originalRows: BodyRow[]

The BodyRows built from the data, before any plugin transformation.

Columns

TableViewModel#current.visibleColumns: FlatColumn[]

The flat columns left after every plugin’s column transformation (hidden columns removed, order applied). Useful for a colspan that spans the whole table:

<th colspan={vm.current.visibleColumns.length}>...</th>
<th colspan={vm.current.visibleColumns.length}>...</th>

TableViewModel#flatColumns: FlatColumn[]

The flat columns of the table before plugin transformations. This is a plain array, not reactive: the column definitions do not change after the view model is built.

Flat columns usually represent the last row of columns in your header, which includes data columns and display columns. They are distinct from group columns which must by definition be one row above other columns.

Plugins

TableViewModel#pluginStates: PluginStates

The state each plugin exposes, keyed by the name you gave the plugin in createTable. Plugin state is made of Box, ReadonlyBox, RecordSet and ArraySet values: read and write their current property.

const { pageIndex, hasNextPage } = vm.pluginStates.page
if (hasNextPage.current) pageIndex.current += 1
const { pageIndex, hasNextPage } = vm.pluginStates.page
if (hasNextPage.current) pageIndex.current += 1
Information:
See also Plugin State.

Debugging

TableViewModel#_debug: ViewModelDebug

Counters for performance work: pluginCount, pluginNames, derivedCount (derivations per chain, e.g. derivedCount.rows), derivationCalls and derivationTimings per derivation, plus resetCounters(), getTotalCalls() and getTotalMs(). The shape may change between minor versions; do not build features on it.