Skip to content

Pivot Table Plugin

The Pivot plugin transforms flat data into a pivot table view.

import '@toolbox-web/grid/features/pivot';
import '@toolbox-web/grid';
import '@toolbox-web/grid/features/pivot';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'region', header: 'Region' },
{ field: 'product', header: 'Product' },
{ field: 'quarter', header: 'Quarter' },
{ field: 'sales', header: 'Sales', type: 'number' },
],
features: {
pivot: {
rowGroupFields: ['region', 'product'],
columnGroupFields: ['quarter'],
valueFields: [{ field: 'sales', aggFunc: 'sum', header: 'Total' }],
},
},
};
grid.rows = salesData;
Active Whether pivot is active
Aggregation Aggregation function
Show total column Show the per-row Total column on the right
Show grand total Show grand total row at the bottom
Show tool panel Show drag-and-drop tool panel
Default expanded Groups expanded by default
Indent width Indent per depth level (px)
Animation Expand/collapse animation

Use the controls to explore the full pivot configuration — toggle active state, totals, grand total, tool panel, default expansion, indent width, aggregation function, and animation style. For sorting, see the Sorting section below.

Event Log

Click groups to expand/collapse and watch the event log. Use the buttons to call the programmatic API. Open the tool panel and drag fields between zones to see pivot-config-change events.

See PivotConfig for the full list of options and defaults.

Key options:

  • showTotals — Shows/hides the per-row Total column on the right (the sum across all pivot columns for each row). This does not affect the aggregated values shown in group rows.
  • showGrandTotal — Shows/hides the grand total row at the bottom.
  • grandTotalInRowModel — When true, the grand total renders as a regular row instead of a sticky footer (useful for data export and copy/paste).

Built-in: sum, avg, count, min, max, first, last

You can provide a custom aggregation function instead of a built-in name:

features: {
pivot: {
rowGroupFields: ['region'],
valueFields: [{
field: 'sales',
aggFunc: (values) => values.reduce((a, b) => a + b * 2, 0),
}],
},
}

Custom aggregators appear as “CUSTOM” in the tool panel and cannot be changed via the UI.

Format aggregated values with a format function on the value field:

valueFields: [{
field: 'revenue',
aggFunc: 'sum',
format: (value) => `$${value.toLocaleString()}`,
}]

If no format is provided, the plugin falls back to the original column’s format function.

To use pivot transformation without exposing the tool panel UI to users:

features: {
pivot: {
showToolPanel: false,
rowGroupFields: ['region'],
columnGroupFields: ['quarter'],
valueFields: [{ field: 'sales', aggFunc: 'sum' }],
},
},

The pivot API methods remain available for programmatic control.

When showToolPanel: true (default), the pivot panel lets users configure the pivot interactively:

  • Drag fields between Row Groups, Column Groups, and Values zones
  • Reorder fields within a zone by dragging
  • Search fields using the filter input at the top of the Available Fields list
  • Change aggregation via the dropdown on each value field (built-in functions only — custom aggregators show “CUSTOM” and cannot be changed via the UI)

The panel fires pivot-config-change events when users modify the configuration.

The plugin supports animated expand/collapse transitions. Animation respects the grid-level animation.mode setting and can be customized per-plugin:

features: {
pivot: {
rowGroupFields: ['region'],
valueFields: [{ field: 'sales', aggFunc: 'sum' }],
animation: 'slide', // 'slide' | 'fade' | false
},
},

Animation is automatically disabled when animation.mode is 'off' or when the user prefers reduced motion ('reduced-motion' mode with system preference).

const plugin = grid.getPluginByName('pivot');
plugin.expand('North__Widget A'); // expand a specific group by key
plugin.collapse('North'); // collapse a group
plugin.expandAll();
plugin.collapseAll();
plugin.getExpandedGroups(); // returns string[] of expanded keys

Pivot columns support interactive sorting — click any column header to cycle through ascending, descending, and unsorted.

When the Multi-Sort plugin is loaded alongside Pivot, shift-click adds secondary sort columns with numbered priority badges. Pivot translates the multi-sort model into hierarchical sorting that respects the group structure.

Click any column header to sort. Shift-click to sort by multiple columns. Click again to reverse. Click a third time to clear.

You can also configure sorting programmatically:

features: {
pivot: {
rowGroupFields: ['region'],
valueFields: [{ field: 'sales', aggFunc: 'sum' }],
sortRows: { by: 'label', direction: 'asc' }, // sort row groups alphabetically
sortColumns: 'desc', // sort column keys descending
},
}

sortRows accepts { by: 'label' | 'value', direction: 'asc' | 'desc', valueField?: string }. When by is 'value', rows are sorted by their total (or by a specific valueField).

Control which groups start expanded:

features: {
pivot: {
defaultExpanded: true, // all groups (default)
defaultExpanded: false, // all collapsed
defaultExpanded: 'North', // expand only the 'North' group
defaultExpanded: ['North', 'South'], // expand specific groups
defaultExpanded: 0, // expand group at index 0
},
}

By default, the grand total renders as a sticky footer. To include it in the row model (useful for exports and copy/paste):

features: {
pivot: {
showGrandTotal: true,
grandTotalInRowModel: true,
},
}
EventDetailDescription
pivot-toggle{ key, expanded, label, depth }Fired when a group is expanded or collapsed
pivot-state-change{ active: boolean }Fired when pivot mode is enabled or disabled
pivot-config-change{ property, field?, zone? }Fired when pivot configuration changes (fields, agg func, etc.)
grid.addEventListener('pivot-toggle', (e) => {
console.log(`${e.detail.label} ${e.detail.expanded ? 'expanded' : 'collapsed'}`);
});
grid.addEventListener('pivot-state-change', (e) => {
console.log(`Pivot is now ${e.detail.active ? 'active' : 'inactive'}`);
});

The pivot plugin supports CSS custom properties for theming. Override these on tbw-grid or a parent container:

PropertyDefaultDescription
--tbw-pivot-group-bgvar(--tbw-color-row-alt)Group row background
--tbw-pivot-group-hovervar(--tbw-color-row-hover)Group row hover
--tbw-pivot-leaf-bgvar(--tbw-color-bg)Leaf row background
--tbw-pivot-grand-total-bgvar(--tbw-color-header-bg)Grand total row
--tbw-pivot-toggle-hover-bgvar(--tbw-color-row-hover)Toggle button hover
--tbw-pivot-section-bgvar(--tbw-color-panel-bg)Panel section background
--tbw-toggle-size1.25emToggle button size
--tbw-animation-duration200msExpand/collapse animation
tbw-grid {
/* Custom pivot styling */
--tbw-pivot-group-bg: #fff3e0;
--tbw-pivot-grand-total-bg: #ffcc80;
--tbw-pivot-toggle-hover-bg: #ffe0b2;
}

The pivot plugin uses these class names:

ClassElement
.pivot-group-rowGrouped summary row
.pivot-leaf-rowDetail/leaf row
.pivot-grand-total-rowGrand total row
.pivot-grand-total-footerSticky footer container
.pivot-toggleExpand/collapse button
.pivot-labelGroup name display
.tbw-pivot-slide-inRow slide animation
.tbw-pivot-fade-inRow fade animation

A development-mode warning is shown if incompatible plugins are loaded together.

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt