Skip to main content
Urbicon UI

Sorting, Grouping & Summaries

Sort by clicking column headers, group rows by any groupable column, and aggregate numeric columns with summary rows.

Sorting & Grouping

Every data column sorts on a header click, cycling ascending, descending, unsorted. sortable: false takes that away; a synthetic column has no value to sort by and never had it.

Grouping is the other way round: you opt a column in. Bucketing an email or a free-text note makes one group per row, so it is not offered to every column that holds a value. groupable: true says yes, groupable: false says no, and with neither set the column follows sortable: true — marking a column sortable already says it is a dimension worth organising the table by.

Start Sorted

viewDefaults.sort is the view's baseline — the header indicator shows it, and users can still change or clear it. A storage binding applies a stored sort after hydration and so beats the default; a stored sort: null is a real value, so a sort the user cleared stays cleared.
Name
Department
Salary
Sofia Martinez
Platform
165000
Alexander Novak
Data
148000
Emma Wilson
Platform
142000
Isabella Singh
Design
140000
Mia Zhang
Product
135000
<Table
  {items}
  {columns}
  viewDefaults={{ sort: { column: 'salary', direction: 'desc' }, pageSize: 5 }}
/>

Grouping with Custom Order

Group rows by any column. The groupOrder array controls the display sequence of groups.
Name
Role
Department
Location
Platform (4 items)
Emma Wilson
Staff Engineer
Platform
Berlin
Sofia Martinez
Engineering Manager
Platform
Munich
Noah Kim
DevOps Engineer
Platform
Hamburg
Ethan Müller
QA Engineer
Platform
Hamburg
Product (3 items)
James Park
Frontend Developer
Product
Remote
Lucas Weber
Backend Developer
Product
Berlin
Mia Zhang
Product Manager
Product
Remote
Design (3 items)
Liam Chen
Product Designer
Design
Hamburg
Olivia Brown
UX Researcher
Design
Munich
Isabella Singh
Design Lead
Design
Berlin
Data (2 items)
Aisha Patel
Data Scientist
Data
Berlin
Alexander Novak
ML Engineer
Data
Munich

Platform (4 items)

Product (3 items)

Design (3 items)

Data (2 items)

<Table
  {items}
  {columns}
  viewDefaults={{ groupBy: 'department' }}
  groupOrder={['Platform', 'Product', 'Design', 'Data']}
/>

Summaries

Summary rows aggregate a column across rows. When the table is grouped, each group gets its own summary row; without grouping, a single total row is appended below the data. Pass prefs={{ defaults: { summaries: […] } }} to enable summaries declaratively — users can also add and remove them at runtime via the header menu or the SmartFilterBar's summary control.

Summaries are a preference, not a view setting. Sorting and grouping decide which rows a reader sees, which makes them worth sharing and worth putting in a link — they live on the view. A summary row changes how the same rows are presented, so it belongs to this reader on this device and stays in web storage: viewDefaults for the former, prefs for the latter.

Per-Group Summaries

Group by department and sum the salary column. Each group renders its own summary row.
Name
Department
Salary
Platform (4 items)
Emma Wilson
Platform
142000
Sofia Martinez
Platform
165000
Noah Kim
Platform
115000
Ethan Müller
Platform
85000
507000
Design (3 items)
Liam Chen
Design
98000
Olivia Brown
Design
88000
Isabella Singh
Design
140000
326000
Product (3 items)
James Park
Product
92000
Lucas Weber
Product
105000
Mia Zhang
Product
135000
332000
Data (2 items)
Aisha Patel
Data
128000
Alexander Novak
Data
148000
276000

Platform (4 items)

Summary for Platform

Salary 507000

Design (3 items)

Summary for Design

Salary 326000

Product (3 items)

Summary for Product

Salary 332000

Data (2 items)

Summary for Data

Salary 276000
<Table
  {items}
  {columns}
  viewDefaults={{ groupBy: 'department', pageSize: 12 }}
  prefs={{ defaults: { summaries: [{ column: 'salary', type: 'sum' }] } }}
/>

A summary is { column, type } plus an optional formatter; the full shape is SummaryConfig. type is sum, avg, min, max or count, and count is the one that does not do arithmetic: it counts the rows that have a value at all. The four others skip rows whose value is not a number, and show a dash when none is.

A summary covers every row matching the current search and filters, not the page on screen. The pager moves under a total that stays put.

Which columns offer summaries is controlled per column: summable: true opts a column in, summable: false opts it out. When the flag is unset, columns with dataType: 'number' are summable automatically. Give the table a preference store (prefs={{ storage: 'employees' }}) and summary selections survive reloads, alongside column visibility and column order.

Header Menu

Every column header exposes a menu (visible on hover and keyboard focus) that bundles the per-column actions, with no SmartFilterBar required. Each entry asks the same question the toolbar's tool of that name asks, so a column is never groupable from one and not from the other:

EntryShown when
Sort ascending / descendinga data column, unless sortable: false
Remove filtersa filter on this column is active
Group by column / Remove groupinggroupable: true, or sortable: true when groupable is unset — never while virtualized
Add summary / Remove summarysummable: true, or dataType: 'number' when summable is unset
Hide columnenableColumnVisibility and hideable ≠ false
Show "Column"one entry per currently hidden column

Try It

Hover a column header and open the ⋮ menu: sort, group by department, summarize salary, or hide a column.
Name
Department
Salary
Emma Wilson
Platform
142000
Liam Chen
Design
98000
Sofia Martinez
Platform
165000
James Park
Product
92000
Aisha Patel
Data
128000
const columns: Column<Employee>[] = [
  { accessor: 'name', title: 'Name', sortable: true },
  { accessor: 'department', title: 'Department', sortable: true, groupable: true },
  {
    accessor: 'salary',
    title: 'Salary',
    sortable: true,
    summable: true,
    dataType: 'number',
    align: 'right'
  }
];

Hiding and restoring columns is covered in Column Configuration → Column Visibility.