Tabulator Grouped Rows with Aggregates — Free JS Snippet

Tabulator Grouped Rows with Aggregates · Tables · Plain HTML, CSS & JS · Live preview

CategoryTables

What's included

Features

Collapsible groups with a fully clickable header
Custom group headers showing count and computed total
Column calculations: sum, avg and count at the top and bottom
columnCalcs "both" gives subtotals per group plus a grand total
Custom aggregate function using full row data (win rate)
Formatted calculation output with currency and labels
setGroupBy() to regroup by region, owner or stage without a rebuild
Progress-bar formatter for probability values

About this UI Snippet

Tabulator Grouped Rows with Aggregates — HTML, CSS & JavaScript

Screenshot of the Tabulator Grouped Rows with Aggregates snippet rendered live

A flat list of records answers "what do we have?". A grouped view with totals answers "how are we doing?" — sales by region, tickets by owner, spend by category. That second question is why finance and operations dashboards are built around grouped tables with subtotals, and it is the shape of data that spreadsheet users already understand. Tabulator can produce it from three pieces of configuration: groupBy, a group header function and column calculations.

groupBy names the field to group on, and Tabulator builds the collapsible sections. groupStartOpen controls whether they begin expanded, and groupToggleElement: 'header' makes the entire header row clickable rather than just a small arrow — a small choice that makes folding much easier. The groupHeader function receives the group's value, its row count and the rows themselves, so it can return anything: this snippet shows the region name, the number of deals, and a right-aligned dollar total computed with a reduce over the group's data. That is why every section header tells you the answer without being expanded.

Aggregates use column calculations. Setting bottomCalc: 'sum' on the Amount column adds a total row, and topCalc: 'avg' adds an average row above. Built-in calculations include sum, avg, count, min and max. The table option columnCalcs: 'both' is the key setting: it shows the calculation rows at the table level and inside every group, so subtotals and a grand total come from one definition. Calculation output can be customised with formatters, which the snippet uses to add currency, a "deals" suffix and a "% avg" label.

The most useful trick is a custom calculation. A calc can be a function that receives the column's values and the full row data, and the winRate function uses the row data to compute the share of closed deals that were won — a figure that depends on a different column from the one it appears under. Finally, setGroupBy() changes the grouping on the fly, so the same data can be viewed by region, owner or stage, or ungrouped by passing false. The aggregates recompute automatically for whichever grouping is active.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant like Claude to add multi-level grouping by region then stage, conditional colouring of over-quota groups, or CSV export of the aggregates.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a grouped sales grid with Tabulator 6 loaded from a CDN (script and CSS).

Requirements:
- Use eleven deals with region, owner, stage (won/open/lost), amount and probability; set groupBy 'region', groupStartOpen, groupToggleElement 'header' and columnCalcs 'both'.
- Write a groupHeader function that returns the region, the deal count and the summed amount.
- Add column calculations: count on the ID column, sum (bottom) and avg (top) on amount with formatted output, avg on probability, and a custom function calc on stage returning the win rate of closed deals from the row data.
- Show probability with the progress formatter and stage as a coloured pill.
- Add buttons that call table.setGroupBy() for region, owner, stage and false, plus Expand all and Collapse all using getGroups().

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="tq-card">
  <div class="tq-bar">
    <div class="tq-group" role="group" aria-label="Group by">
      <span>Group by</span>
      <button type="button" data-g="region" class="on">Region</button>
      <button type="button" data-g="owner">Owner</button>
      <button type="button" data-g="stage">Stage</button>
      <button type="button" data-g="">None</button>
    </div>
    <div class="tq-expand">
      <button type="button" id="tqOpen">Expand all</button>
      <button type="button" id="tqClose">Collapse all</button>
    </div>
  </div>
  <div id="tqTable"></div>
</div>

Step by step

How to Use

  1. 1
    Read the group headersEach region shows its deal count and total value in the header, even when collapsed.
  2. 2
    Fold groupsClick a group header to collapse it, or use Expand all and Collapse all.
  3. 3
    Read the aggregate rowsInside each group, an average appears above and sum, count and win rate appear below; a grand total closes the table.
  4. 4
    RegroupSwitch Group by to Owner or Stage. Headers and aggregates recompute for the new grouping.
  5. 5
    UngroupChoose None to see the flat list again with a single table-wide total.

Real-world uses

Common Use Cases

Sales and pipeline reports
Show revenue by region with subtotals. For a flat searchable dataset use the Tabulator filterable grid.
Finance and expense tables
Group spend by category or cost centre with sums and averages.
ADMIN
Support and operations queues
Group tickets by owner or status and see workloads at a glance.
Learning custom aggregates
See how a calculation can depend on a different column's data.

Got questions?

Frequently Asked Questions

Set columnCalcs: "both" (or "group") and define topCalc or bottomCalc on the columns you want aggregated.

Tabulator includes sum, avg, count, min, max and a few others, and you can supply your own function.

Pass a function as the calc. It receives the column values, the row data and any params, and returns the value to display.

Call table.setGroupBy("field"). Pass false to remove grouping.

Provide a groupHeader function that receives the value, count, data and group, and returns an HTML string.

Loop over table.getGroups() and call hide() on each one, or show() to expand.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from Tabulator, so in a framework project install it with npm install tabulator-tables (or react-tabulator) instead of the CDN tag, create it in useEffect / onMounted / ngAfterViewInit and wait for the tableBuilt event, and release it with destroy() when the component unmounts.