Documentation

Nested Tables

Nested tables allow each level of hierarchical data to have its own independent grid structure with completely different columns, enabling you to display different information at each nesting level.

Static Nested Tables (Pre-loaded Data)

This example demonstrates nested tables with all data pre-loaded. Expand companies to see their divisions with detailed metrics including revenue, profit margin, headcount, and location.

Dynamic Nested Tables (Lazy Loading)

This example shows lazy-loading nested tables where divisions are fetched on-demand when you expand company rows. The onRowGroupExpand handler manages dynamic data loading with built-in loading states.

What Are Nested Tables?

Nested tables extend the row grouping feature by allowing each level of your hierarchy to have its own independent table structure. While row grouping shows child rows with the same columns as the parent, nested tables let you define completely different columns for each level.

Key Difference: Row Grouping vs Nested Tables

  • Row Grouping: All levels share the same column structure. Child rows display the same columns as parent rows.
  • Nested Tables: Each level has its own independent column structure. Parent and child levels can have completely different columns.

Basic Setup

To enable nested tables, add the nestedTable property to your expandable column's HeaderObject. This property defines the column structure and configuration for the child table that appears when a row is expanded.

⚠️ Important

  • You must still use the rowGrouping prop to define the hierarchy (e.g., rowGrouping={["divisions"]})
  • The expandable property must be set to true on the column
  • Each level can have its own nestedTable configuration for multi-level nesting

Nested Table Configuration

PropertyRequiredDescriptionExample
HeaderObject.nestedTable
NestedTableConfig (extends all SimpleTable props)
Optional
Configuration for nested tables that allows each level of row grouping to have its own independent grid structure with different columns and settings. When a row is expanded, its child data is displayed in a completely separate table with its own headers, column configuration, and features. The nested table config accepts all SimpleTable props, allowing complete customization at each nesting level.
NestedTableConfig.defaultHeaders
Required
Array of HeaderObject definitions that define the column structure for the nested table. This allows each nesting level to have completely different columns than its parent.
NestedTableConfig.* (Most SimpleTable Props)
Optional
In addition to defaultHeaders, the nestedTable config accepts most props from the SimpleTable component. This includes autoExpandColumns, enableRowSelection, columnResizing, theme, customTheme, shouldPaginate, pageSize, defaultSortConfig, enableColumnFiltering, onCellClick, onCellChange, onRowGroupExpand, and more. Note: Some props are automatically inherited from the parent table (rows, loadingStateRenderer, errorStateRenderer, emptyStateRenderer, tableEmptyStateRenderer, and icon props) and cannot be overridden in nested tables. Each nested table can be configured independently with its own settings. See the API Reference for the complete list of available props.

Understanding the Hierarchy

The demos above show a two-level nested table structure with completely different columns at each level:

Level 0: Companies (9 columns)

High-level company overview with industry, headquarters, market cap, CEO, revenue, and employee count.

Level 1: Divisions (6 columns)

Division-level details including division ID, division name, revenue, profit margin, headcount, and location.

💡 Multi-Level Support

These demos show two levels of nesting, but nested tables support unlimited nesting depth. You can create three, four, or more levels by adding nestedTable configurations at each level (e.g., Companies → Divisions → Teams → Members → Projects).

Data Structure

The data structure for nested tables is the same as row grouping - use nested arrays with property names matching your rowGrouping configuration:

const data = [
  {
    // Company level (Level 0)
    companyName: "TechCorp Global",
    industry: "Technology",
    founded: 2015,
    employees: 50000,
    // ... other company fields
    
    // Child divisions (Level 1)
    divisions: [
      {
        divisionId: "DIV-001",
        divisionName: "Cloud Services",
        revenue: "$15B",
        profitMargin: "35%",
        headcount: 250,
        location: "San Francisco, CA"
      },
      // ... more divisions
    ]
  },
  // ... more companies
];

Inherited Props

For consistency and convenience, certain props are automatically inherited from the parent table and cannot be overridden in nested tables. This ensures a unified experience across all nesting levels.

📋 Props Inherited from Parent

These props are automatically inherited and should not be specified in the nestedTable config:

  • rows - Data is automatically provided from the parent row's nested array
  • loadingStateRenderer, errorStateRenderer, emptyStateRenderer, tableEmptyStateRenderer - State renderers are shared across all levels
  • Icon props (expandIcon, filterIcon, sortUpIcon, sortDownIcon, etc.) - Icons are consistent across all nesting levels

Dynamic Nested Tables

As shown in the dynamic demo above, nested tables support lazy-loading at each level using the onRowGroupExpand callback. You can specify different handlers for each nesting level, allowing you to fetch data on demand when users expand rows.

🚀 Benefits of Dynamic Loading

  • Faster initial page load - only fetch top-level data
  • Reduced memory usage - load child data only when needed
  • Better performance with large hierarchical datasets
  • Independent handlers for each nesting level
  • Built-in loading, error, and empty state management

💡 Two Loading Patterns

  • Static/Pre-loaded: All data is loaded upfront in the initial rows prop. Best for smaller datasets or when all data is readily available. See the first demo above.
  • Dynamic/Lazy-loaded: Child data is fetched on-demand when users expand rows using onRowGroupExpand handlers. Best for large datasets, API-driven data, or when initial load time matters. See the second demo above for implementation details.

Combining with Other Features

Nested tables are fully-featured SimpleTable instances, meaning they can receive most of the same props and configuration options as a regular table (except for inherited props). Each nested table can be configured independently with its own settings:

🎯 Full SimpleTable API Support

The nestedTable config accepts any SimpleTable prop, allowing complete customization at each nesting level.

Common configurations include:

  • Row Selection: Enable enableRowSelection to allow selection at that nesting level
  • Column Resizing: Set columnResizing to enable/disable resizing independently
  • Auto Expand Columns: Use autoExpandColumns to make columns fill available width
  • Sorting & Filtering: Configure defaultSortConfig, enableColumnFiltering, and other sorting/filtering options per level
  • Themes: Apply different theme or customTheme settings to each nested table (see Custom Theme)
  • Cell Renderers: Use custom cellRenderer, valueFormatter, and headerRenderer functions with level-specific logic
  • Pagination: Enable shouldPaginate with custom pageSize for nested tables
  • Callbacks: Add onCellClick, onCellChange, and other event handlers specific to that level
  • And more: Any prop from the API Reference can be used in the nested table configuration

See the demos above for complete implementation examples of both static and dynamic nested tables.

Related Features