Skip to content
AdaptTable

Vue column layout and row controls

Compose Vue column resizing, grouped headers, row pinning, spans, details and host-owned row actions.

These examples use @adapttable/vue-unstyled. Import matching feature paths from your selected adapter so its own kit renders the controls. See Vue installation and providers.

resizableColumns(), collapsibleColumnGroups(), multiSort() and fitColumns() return StaticTableFeature. Desktop resize/group controls operate on the same controlled or local column layout; mobile cards honor visibility and ordering without desktop handles. Resize actions stop when the feature is removed or deactivated. ColumnResizeHandleOptions and ColumnResizeHandleProps describe the neutral handle’s cancellation options and semantic pointer/keyboard props for adapter implementations.

import { h, shallowRef } from "vue";
import type { RowPinState } from "@adapttable/vue";
import { rowPinning } from "@adapttable/vue-unstyled/row-pinning";
import { pinnedSummaryRows } from "@adapttable/vue-unstyled/pinned-summary-rows";
import { extraRows } from "@adapttable/vue-unstyled/extra-rows";
import { rowAppearance } from "@adapttable/vue-unstyled/row-appearance";
interface Person {
id: string;
name: string;
score: number;
}
const pins = shallowRef<RowPinState>({ top: [], bottom: [] });
const features = [
rowPinning({
pinnedRowIds: pins,
onPinnedRowIdsChange: (next) => {
pins.value = next;
},
}),
pinnedSummaryRows<Person>({
bottom: [{ id: "total", name: "Total", score: 30 }],
}),
extraRows([
{
key: "note",
kind: "fullWidth",
render: () => h("p", "Scores are provisional"),
},
]),
rowAppearance<Person>({
rowClassName: (row) => (row.score < 10 ? "low-score" : undefined),
}),
];

rowPinning(options?: RowPinningFeatureOptions) accepts reactive pinnedRowIds: RowPinState and onPinnedRowIdsChange(next). Controlled requests require host acceptance. Uncontrolled pins use the table’s URL backend. Grouped/tree tables refuse data-row pinning; pinnedSummaryRows still works there. useRowPinning(options: RowPinningOptions<TRow>) is the lower-level computed controller with state, sideOf, pin, unpin and actions; options require reactive enabled, getRowId and labels.

pinnedSummaryRows<TRow>(rows: PinnedRows<TRow>) accepts independent top and bottom arrays, rendered through ordinary columns but outside filtering, sorting, pagination and selection. The host computes their values.

For computed summaries, aggregate<TRow>(spec, options?) from @adapttable/vue returns a SummaryRowFn<TRow>: a function from rows to a record of column keys and Vue-renderable values. AggregateSpec maps each column key to a registered operation name or an Aggregator<TValue> callback that receives the column’s values and returns a VNodeChild. AggregateOptions<TRow> retains the neutral aggregation options and accepts format(value, key): VNodeChild, so formatted results can contain Vue nodes. For example, aggregate<Person>({ score: "sum" })(people) computes a score summary for host-rendered content. The binding uses the shared aggregation registry; this helper does not install a footer summary row.

cellSpan<TRow>(getCellSpan: GetCellSpan<TRow>, appearance?: CellSpanAppearance) uses a callback receiving GetCellSpanArgs: row, column, dataset row index, column index and visual sectionRows/sectionRowIndex. Return CellSpanRequest with optional rowSpan/colSpan; omitted dimensions are one. Appearance is "merged" or "plain". For example, cellSpan<Person>(({ column }) => column.key === "name" ? { colSpan: 2 } : undefined) merges the name with its next visible column on desktop. Neutral resolveCellSpan(args, getCellSpan, maxColumns, maxRows) clamps requested geometry; the Vue adapter entry re-exports it for custom projections.

extraRows(rows: readonly ExtraRow[]) accepts stable keys, kind: "separator" | "fullWidth", optional beforeRowId, and optional Vue render(): VNodeChild. Omit the row ID to append. ExtraEntry is the corresponding projected variant; ExtraRowKind names the two kinds. rowAppearance<TRow>(options: RowAppearanceOptions<TRow>) accepts rowClassName(row, index), rowStyle and rowHeight. Indices are relative to the loaded source with its page offset, rather than counting structural rows. HeadlessRowsOptions<TRow> groups these presentation inputs, spans, summaries and optional pin offset for custom projectors. HeadlessBodySlot<TRow> aliases the resulting Vue TableBodySlot union.

rowActions<TRow>(actions?: readonly RowAction<TRow>[], handlers?: RowMutationHandlers<TRow>) combines host actions with optional add/duplicate/delete callbacks. Each action has a key, label and optional onClick(row); the host supplies its effect. RowMutationHandlers offers onAddRow(), onDuplicateRow(row), onDeleteRow(row) and confirmDeleteRow (defaults to true). Native confirmation uses the browser dialog unless the table’s confirm: ConfirmHandler overrides it. A cancelled confirmation does not call the host callback.

useRowMutations(MaybeRefOrGetter<UseRowMutationsOptions<TRow>>) returns a computed RowMutationsState: canAdd, addRow() and mutation actions. RowMutationAction<TRow> preserves the host’s actual return value, including a persistence promise. rowActionControls(input: RowActionControlsInput<TRow>) produces labeled, semantic controls and guards delayed confirmation against feature removal. Use it when implementing a kit; the native table already uses this projection.

Use the Vue live demo to switch adapters and the Vue Feature Lab to compose features. The feature index lists native imports and API reference documents the binding and controlled contracts.

Third-party notices