CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-table

Hooks for building lightweight, fast and extendable datagrids for React

Pending
Overview
Eval results
Files

grouping.mddocs/

Data Grouping

React Table provides comprehensive data grouping capabilities through the useGroupBy hook. This feature allows you to group rows by column values, create hierarchical data structures, and apply aggregation functions to grouped data.

Capabilities

Data Grouping (useGroupBy)

Enables row grouping by column values with support for multiple grouping levels, custom aggregation functions, and expandable group headers.

/**
 * Adds row grouping capabilities to the table
 * @param hooks - Hook registration object
 */
function useGroupBy(hooks: Hooks): void;

/**
 * Default grouping function that groups rows by column accessor values
 * @param rows - Array of rows to group
 * @param columnId - Column ID to group by
 * @returns Grouped rows structure
 */
function defaultGroupByFn(rows: Row[], columnId: string): Row[];

interface GroupByInstance {
  /** Toggle grouping for a specific column */
  toggleGroupBy: (columnId: string, value?: boolean) => void;
  /** Set the groupBy configuration */
  setGroupBy: (groupBy: string[]) => void;
  /** Rows before grouping was applied */
  preGroupedRows: Row[];
  /** Flat rows before grouping */
  preGroupedFlatRows: Row[];
  /** Rows after grouping */
  groupedRows: Row[];
  /** Flat rows after grouping */
  groupedFlatRows: Row[];
  /** Non-grouped rows mapped by ID */
  nonGroupedRowsById: Record<string, Row>;
}

interface GroupByColumnInstance {
  /** Whether this column can be grouped */
  canGroupBy: boolean;
  /** Whether this column is currently grouped */
  isGrouped: boolean;
  /** Index of this column in the groupBy array */
  groupedIndex: number;
  /** Toggle grouping for this column */
  toggleGroupBy: (value?: boolean) => void;
  /** Get props for group by toggle UI */
  getGroupByToggleProps: (userProps?: any) => object;
}

interface GroupByState {
  /** Array of column IDs to group by, in order */
  groupBy: string[];
}

Usage Examples:

import React from 'react';
import { useTable, useGroupBy } from 'react-table';

function GroupedTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    state: { groupBy },
    setGroupBy,
  } = useTable(
    {
      columns,
      data,
      initialState: {
        groupBy: ['category'], // Group by category initially
      },
    },
    useGroupBy // Add grouping functionality
  );

  return (
    <div>
      <div>
        <label>
          Group By:
          <select
            value={groupBy[0] || ''}
            onChange={e => setGroupBy(e.target.value ? [e.target.value] : [])}
          >
            <option value="">No Grouping</option>
            <option value="category">Category</option>
            <option value="status">Status</option>
          </select>
        </label>
      </div>
      
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>
                  {column.render('Header')}
                  {column.canGroupBy && (
                    <button
                      {...column.getGroupByToggleProps()}
                      style={{
                        marginLeft: '8px',
                        backgroundColor: column.isGrouped ? '#007bff' : '#6c757d',
                        color: 'white',
                        border: 'none',
                        padding: '2px 6px',
                        borderRadius: '3px',
                        fontSize: '12px',
                      }}
                    >
                      {column.isGrouped ? 'Ungroup' : 'Group'}
                    </button>
                  )}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            
            // Group header row
            if (row.isGrouped) {
              return (
                <tr {...row.getRowProps()}>
                  <td
                    {...row.cells[0].getCellProps()}
                    colSpan={columns.length}
                    style={{
                      fontWeight: 'bold',
                      backgroundColor: '#f8f9fa',
                      padding: '8px',
                    }}
                  >
                    {row.groupByID}: {row.groupByVal} ({row.subRows.length} items)
                  </td>
                </tr>
              );
            }
            
            // Regular data row
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.isGrouped ? (
                      <span style={{ fontWeight: 'bold' }}>
                        {cell.render('Cell')} ({row.subRows.length})
                      </span>
                    ) : cell.isAggregated ? (
                      cell.render('Aggregated')
                    ) : cell.isPlaceholder ? null : (
                      cell.render('Cell')
                    )}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Multi-level Grouping

Group by multiple columns to create nested hierarchical structures:

const table = useTable(
  {
    columns,
    data,
    initialState: {
      groupBy: ['category', 'status'], // Group by category, then status
    },
  },
  useGroupBy
);

Custom Aggregation Functions

Define how grouped data should be aggregated for display:

const columns = [
  {
    Header: 'Product',
    accessor: 'product',
  },
  {
    Header: 'Category',
    accessor: 'category',
  },
  {
    Header: 'Sales',
    accessor: 'sales',
    aggregate: 'sum', // Built-in sum aggregation
    Aggregated: ({ value }) => `Total: ${value}`,
  },
  {
    Header: 'Units',
    accessor: 'units',
    aggregate: (leafValues) => {
      // Custom aggregation function
      return leafValues.reduce((sum, val) => sum + val, 0);
    },
    Aggregated: ({ value }) => `${value} units`,
  },
];

Built-in Aggregation Functions

React Table provides several built-in aggregation functions:

// Built-in aggregation functions
const aggregations = {
  /** Sum all values */
  sum: (leafValues: any[]) => number;
  /** Find minimum value */  
  min: (leafValues: any[]) => number;
  /** Find maximum value */
  max: (leafValues: any[]) => number;
  /** Calculate average */
  average: (leafValues: any[]) => number;
  /** Calculate median */
  median: (leafValues: any[]) => number;
  /** Get unique values as array */
  unique: (leafValues: any[]) => any[];
  /** Count unique values */
  uniqueCount: (leafValues: any[]) => number;
  /** Count all values */
  count: (leafValues: any[]) => number;
  /** Get min-max range as string */
  minMax: (leafValues: any[]) => string;
};

Types

interface GroupByRow extends Row {
  /** Whether this row represents a group header */
  isGrouped: boolean;
  /** Column ID this group is grouped by */
  groupByID?: string;
  /** Value this group represents */
  groupByVal?: any;
  /** Depth level of this group */
  depth: number;
  /** Leaf rows in this group */
  leafRows?: Row[];
  /** Sub-groups or sub-rows */
  subRows: Row[];
}

interface GroupByCell extends Cell {
  /** Whether this cell is grouped (group header cell) */
  isGrouped: boolean;
  /** Whether this cell shows aggregated data */
  isAggregated: boolean;
  /** Whether this cell is a placeholder in a grouped row */
  isPlaceholder: boolean;
}

interface Column {
  /** Aggregation function or function name */
  aggregate?: string | ((leafValues: any[], childRows: Row[]) => any);
  /** Component to render aggregated values */
  Aggregated?: Renderer;
  /** Whether this column can be grouped */
  canGroupBy?: boolean;
  /** Whether to disable grouping for this column */
  disableGroupBy?: boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-table

docs

built-in-types.md

column-management.md

core-table.md

filtering.md

grouping.md

index.md

layout.md

pagination.md

row-features.md

sorting.md

utilities.md

tile.json