or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

charts-visualization.mddata-processing.mdfiltering-search.mdimport-export.mdindex.mdrow-operations.mdselection-interaction.mdui-components.md
tile.json

row-operations.mddocs/

Row Operations

Advanced row manipulation including grouping, pivoting, aggregation, master-detail functionality, and tree data operations for comprehensive data organization and analysis.

Capabilities

Row Grouping

Hierarchical data organization with expand/collapse functionality and custom group renderers.

/**
 * Row grouping configuration
 */
interface RowGroupingDisplayType {
  /** Single column grouping */
  singleColumn?: boolean;
  /** Multiple column grouping */
  multipleColumns?: boolean;
  /** Group rows display */
  groupRows?: boolean;
  /** Custom grouping display */
  custom?: boolean;
}

/**
 * Group cell renderer parameters
 */
interface ICellRendererParams {
  /** The value for the cell */
  value: any;
  /** Formatted value for display */
  valueFormatted?: string;
  /** The row node */
  node: RowNode;
  /** The column definition */
  colDef: ColDef;
  /** The column instance */
  column: Column;
  /** Row index */
  rowIndex: number;
  /** Grid API */
  api: GridApi;
  /** Column API */
  columnApi: ColumnApi;
  /** Grid context */
  context: any;
  /** Refresh function */
  refreshCell: () => void;
}

/**
 * Auto group column definition
 */
interface AutoGroupColumnDef extends ColDef {
  /** Header name for the group column */
  headerName?: string;
  /** Field for the group column */
  field?: string;
  /** Cell renderer for group cells */
  cellRenderer?: string | ICellRendererFunc;
  /** Cell renderer parameters */
  cellRendererParams?: any;
  /** Value getter for group values */
  valueGetter?: string | ValueGetterFunc;
  /** Key creator for group keys */
  keyCreator?: (params: any) => string;
}

Usage Example:

import { RowGroupingModule } from "ag-grid-enterprise";

const columnDefs: ColDef[] = [
  { field: "country", rowGroup: true, hide: true },
  { field: "sport", rowGroup: true, hide: true },
  { field: "athlete" },
  { field: "age" },
  { field: "gold", aggFunc: "sum" },
  { field: "silver", aggFunc: "sum" },
  { field: "bronze", aggFunc: "sum" }
];

const gridOptions: GridOptions = {
  modules: [RowGroupingModule],
  columnDefs,
  
  // Row grouping configuration
  groupDisplayType: "multipleColumns",
  showOpenedGroup: true,
  
  // Auto group column configuration
  autoGroupColumnDef: {
    headerName: "Athlete Details",
    minWidth: 300,
    cellRendererParams: {
      suppressCount: false,
      checkbox: false,
      innerRenderer: (params) => {
        return params.data ? params.data.athlete : params.value;
      }
    }
  },
  
  // Group default expanded
  groupDefaultExpanded: 1,
  
  // Aggregation functions
  aggFuncs: {
    avg: (params) => {
      const values = params.values.filter(v => v != null);
      return values.length > 0 ? values.reduce((a, b) => a + b) / values.length : null;
    }
  },
  
  // Group row renderer
  groupRowRenderer: "agGroupCellRenderer",
  groupRowRendererParams: {
    suppressCount: false,
    checkbox: false,
    innerRenderer: (params) => {
      return `<span style="font-weight: bold">${params.value}</span>`;
    }
  }
};

// Programmatic row grouping
gridApi.setRowGroupColumns(["country", "sport"]);
gridApi.setGroupDisplayType("singleColumn");

// Expand/collapse groups
gridApi.expandAll();
gridApi.collapseAll();

// Expand specific group
const countryNodes = [];
gridApi.forEachNode(node => {
  if (node.group && node.level === 0) {
    countryNodes.push(node);
  }
});
gridApi.setRowNodeExpanded(countryNodes[0], true);

Pivoting

Transform row data into column data with aggregation support for analytical views.

/**
 * Pivot mode configuration
 */
interface PivotModeOptions {
  /** Enable pivot mode */
  pivotMode?: boolean;
  /** Pivot columns */
  pivotColumnGroupTotals?: "before" | "after" | "never";
  /** Pivot row totals */
  pivotRowTotals?: "before" | "after" | "never";
  /** Function to generate pivot column group definitions */
  processPivotResultColDef?: (colDef: ColDef) => void;
  /** Function to generate pivot column group definitions */
  processPivotResultColGroupDef?: (colGroupDef: ColGroupDef) => void;
}

/**
 * Pivot column group definition
 */
interface PivotColumnGroupDef extends ColGroupDef {
  /** Pivot keys for this column group */
  pivotKeys?: string[];
  /** Total column IDs for this pivot group */
  pivotTotalColumnIds?: string[];
}

/**
 * Value column definition for pivoting
 */
interface ValueColumnDef {
  /** Column ID */
  colId: string;
  /** Aggregation function */
  aggFunc: string | IAggFunc;
  /** Display name */
  displayName?: string;
}

Usage Example:

import { PivotModule } from "ag-grid-enterprise";

const columnDefs: ColDef[] = [
  { field: "country", rowGroup: true },
  { field: "sport", rowGroup: true },
  { field: "year", pivot: true },
  { field: "gold", aggFunc: "sum" },
  { field: "silver", aggFunc: "sum" },
  { field: "bronze", aggFunc: "sum" }
];

const gridOptions: GridOptions = {
  modules: [PivotModule],
  columnDefs,
  
  // Enable pivot mode
  pivotMode: true,
  
  // Pivot configuration
  pivotColumnGroupTotals: "before",
  pivotRowTotals: "after",
  
  // Custom pivot column processing
  processPivotResultColDef: (colDef) => {
    // Customize pivot column appearance
    if (colDef.pivotKeys && colDef.pivotKeys.includes("2000")) {
      colDef.cellStyle = { backgroundColor: "#e6f3ff" };
    }
  },
  
  processPivotResultColGroupDef: (colGroupDef) => {
    // Customize pivot column group appearance
    colGroupDef.headerClass = "pivot-group-header";
  }
};

// Programmatic pivot operations
gridApi.setPivotMode(true);
gridApi.setPivotColumns(["year"]);
gridApi.setRowGroupColumns(["country", "sport"]);
gridApi.setValueColumns([
  { colId: "gold", aggFunc: "sum" },
  { colId: "silver", aggFunc: "sum" }
]);

// Get pivot result columns
const pivotResultColumns = gridApi.getPivotResultColumns();
console.log("Pivot columns:", pivotResultColumns?.length);

Aggregation

Custom aggregation functions for summarizing grouped data with built-in and custom aggregation support.

/**
 * Aggregation function interface
 */
interface IAggFunc {
  /** Aggregation function implementation */
  (params: IAggFuncParams): any;
}

/**
 * Aggregation function parameters
 */
interface IAggFuncParams {
  /** Values to aggregate */
  values: any[];
  /** Column being aggregated */
  column: Column;
  /** Column definition */
  colDef: ColDef;
  /** Row group columns */
  rowGroupColumns: Column[];
  /** Value columns */
  valueColumns: Column[];
  /** Grid API */
  api: GridApi;
  /** Column API */  
  columnApi: ColumnApi;
}

/**
 * Built-in aggregation functions
 */
type BuiltInAggFunc = "sum" | "min" | "max" | "count" | "avg" | "first" | "last";

Usage Example:

import { AggregationModule } from "ag-grid-enterprise";

const gridOptions: GridOptions = {
  modules: [AggregationModule],
  
  // Custom aggregation functions
  aggFuncs: {
    // Custom average that ignores zeros
    avgNonZero: (params) => {
      const nonZeroValues = params.values.filter(value => value != null && value !== 0);
      if (nonZeroValues.length === 0) return null;
      return nonZeroValues.reduce((a, b) => a + b, 0) / nonZeroValues.length;
    },
    
    // Custom median aggregation
    median: (params) => {
      const sortedValues = params.values
        .filter(value => value != null)
        .sort((a, b) => a - b);
      
      if (sortedValues.length === 0) return null;
      
      const mid = Math.floor(sortedValues.length / 2);
      return sortedValues.length % 2 === 0
        ? (sortedValues[mid - 1] + sortedValues[mid]) / 2
        : sortedValues[mid];
    },
    
    // Custom weighted average
    weightedAvg: (params) => {
      // Assumes weight is in the next column
      const weights = params.api.getValue("weight", params.node);
      let totalValue = 0;
      let totalWeight = 0;
      
      params.values.forEach((value, index) => {
        if (value != null && weights[index] != null) {
          totalValue += value * weights[index];
          totalWeight += weights[index];
        }
      });
      
      return totalWeight > 0 ? totalValue / totalWeight : null;
    }
  }
};

const columnDefs: ColDef[] = [
  { field: "country", rowGroup: true },
  { field: "sport", rowGroup: true },
  { field: "gold", aggFunc: "sum" },
  { field: "silver", aggFunc: "avgNonZero" }, // Custom aggregation
  { field: "bronze", aggFunc: "median" },     // Custom aggregation
  { 
    field: "score", 
    aggFunc: "weightedAvg",  // Custom weighted average
    headerName: "Weighted Score"
  }
];

Master Detail

Expandable row details with nested grids or custom detail components.

/**
 * Master detail configuration
 */
interface MasterDetailGridOptions {
  /** Enable master detail */
  masterDetail?: boolean;
  /** Detail cell renderer */
  detailCellRenderer?: string | ICellRendererFunc;
  /** Detail cell renderer parameters */
  detailCellRendererParams?: any;
  /** Detail row height */
  detailRowHeight?: number;
  /** Detail row auto height */
  detailRowAutoHeight?: boolean;
  /** Keep detail rows */
  keepDetailRows?: boolean;
  /** Keep detail row count */
  keepDetailRowsCount?: number;
}

/**
 * Detail cell renderer parameters
 */
interface IDetailCellRendererParams extends ICellRendererParams {
  /** Detail grid options */
  detailGridOptions?: GridOptions;
  /** Get detail row data function */
  getDetailRowData?: (params: GetDetailRowDataParams) => void;
  /** Template for detail view */
  template?: string;
}

/**
 * Get detail row data parameters
 */
interface GetDetailRowDataParams {
  /** Master row node */
  node: RowNode;
  /** Master row data */
  data: any;
  /** Success callback */
  successCallback: (rowData: any[]) => void;
}

Usage Example:

import { MasterDetailModule } from "ag-grid-enterprise";

const gridOptions: GridOptions = {
  modules: [MasterDetailModule],
  
  // Enable master detail
  masterDetail: true,
  detailCellRenderer: "agDetailCellRenderer",
  detailRowHeight: 310,
  detailCellRendererParams: {
    // Detail grid configuration
    detailGridOptions: {
      columnDefs: [
        { field: "callId", headerName: "Call ID" },
        { field: "direction", headerName: "Direction" },
        { field: "number", headerName: "Number" },
        { field: "duration", headerName: "Duration" },
        { field: "switchCode", headerName: "Switch Code" }
      ],
      defaultColDef: {
        flex: 1,
        minWidth: 120
      }
    },
    
    // Function to get detail data
    getDetailRowData: (params) => {
      // Simulate async data loading
      setTimeout(() => {
        const detailData = [
          { callId: 1, direction: "Out", number: "555-1234", duration: 120, switchCode: "SW001" },
          { callId: 2, direction: "In", number: "555-5678", duration: 240, switchCode: "SW002" }
        ];
        params.successCallback(detailData);
      }, 500);
    }
  }
};

// Custom detail cell renderer
const customDetailCellRenderer = {
  init(params) {
    this.eGui = document.createElement("div");
    this.eGui.innerHTML = `
      <div style="padding: 20px; background: #f5f5f5;">
        <h3>Details for ${params.data.name}</h3>
        <div>
          <p><strong>Full Address:</strong> ${params.data.address}</p>
          <p><strong>Phone:</strong> ${params.data.phone}</p>
          <p><strong>Email:</strong> ${params.data.email}</p>
          <div style="margin-top: 15px;">
            <button onclick="alert('Edit clicked')">Edit</button>
            <button onclick="alert('Delete clicked')">Delete</button>
          </div>
        </div>
      </div>
    `;
  },
  
  getGui() {
    return this.eGui;
  }
};

// Register custom detail renderer
gridOptions.components = {
  customDetailCellRenderer: customDetailCellRenderer
};

Tree Data Operations

Advanced tree data manipulation with expand/collapse, level management, and custom tree operations.

/**
 * Tree data API operations
 */
interface TreeDataService {
  /** Expand all tree nodes */
  expandAll(): void;
  /** Collapse all tree nodes */
  collapseAll(): void;
  /** Expand to level */
  expandToLevel(level: number): void;
  /** Get tree path for node */
  getTreePath(node: RowNode): string[];
  /** Check if node is tree data */
  isTreeData(node: RowNode): boolean;
}

/**
 * Tree data path parameters
 */
interface TreeDataPathParams {
  /** Tree path array */
  path: string[];
  /** Tree level */
  level: number;
  /** Parent node */
  parent?: RowNode;
}

Usage Example:

import { TreeDataModule } from "ag-grid-enterprise";

// Hierarchical file system data
const treeData = [
  {
    filePath: ["Documents"],
    name: "Documents",
    type: "folder",
    size: null
  },
  {
    filePath: ["Documents", "Projects"],
    name: "Projects",
    type: "folder", 
    size: null
  },
  {
    filePath: ["Documents", "Projects", "project1.txt"],
    name: "project1.txt",
    type: "file",
    size: 1024
  }
];

const gridOptions: GridOptions = {
  modules: [TreeDataModule],
  
  treeData: true,
  getDataPath: (data) => data.filePath,
  groupDefaultExpanded: -1, // Expand all levels
  
  columnDefs: [
    {
      field: "name",
      cellRenderer: "agGroupCellRenderer",
      cellRendererParams: {
        innerRenderer: (params) => {
          const icon = params.data?.type === "folder" ? "📁" : "📄";
          return `${icon} ${params.value}`;
        }
      }
    },
    { field: "type" },
    { 
      field: "size",
      valueFormatter: (params) => {
        return params.value ? `${params.value} bytes` : "";
      }
    }
  ],
  
  rowData: treeData
};

// Tree operations
gridApi.expandAll();
gridApi.collapseAll();
gridApi.expandToLevel(2);

// Get tree path for specific node
gridApi.forEachNode(node => {
  if (node.data?.name === "project1.txt") {
    const path = gridApi.getDataPath(node.data);
    console.log("File path:", path.join("/"));
  }
});

Row Numbers

Display row numbers in a dedicated column with optional row resizing and selection integration.

/**
 * Row numbers configuration options
 */
interface RowNumbersOptions {
  /** Width of the row numbers column */
  width?: number;
  /** Minimum width of the row numbers column */
  minWidth?: number;
  /** Maximum width of the row numbers column */
  maxWidth?: number;
  /** Whether the column is resizable */
  resizable?: boolean;
  /** Disable row selection when clicking row numbers */
  suppressCellSelectionIntegration?: boolean;
  /** Enable row height resizing handles */
  enableRowResizer?: boolean;
  /** Custom value formatter for row numbers */
  valueFormatter?: (params: ValueFormatterParams) => string;
  /** Custom value getter for row numbers */
  valueGetter?: (params: ValueGetterParams) => any;
  /** Header tooltip text */
  headerTooltip?: string;
  /** Custom context menu items */
  contextMenuItems?: (string | MenuItemDef)[];
  /** Cell click handler */
  onCellClicked?: (event: CellClickedEvent) => void;
  /** Cell double-click handler */
  onCellDoubleClicked?: (event: CellDoubleClickedEvent) => void;
  /** Cell context menu handler */
  onCellContextMenu?: (event: CellContextMenuEvent) => void;
}

Usage Example:

import { RowNumbersModule } from "ag-grid-enterprise";

// Basic row numbers
const gridOptions: GridOptions = {
  modules: [RowNumbersModule],
  rowNumbers: true,
  
  columnDefs: [
    { field: "name" },
    { field: "age" },
    { field: "country" }
  ]
};

// Advanced configuration with row resizing
const gridOptions: GridOptions = {
  modules: [RowNumbersModule],
  
  rowNumbers: {
    width: 80,
    resizable: true,
    enableRowResizer: true, // Add drag handles for row height adjustment
    suppressCellSelectionIntegration: false, // Allow row selection on click
    valueFormatter: (params) => `#${params.value}`,
    headerTooltip: "Row Numbers - Click to select entire row"
  },
  
  // Enable cell selection for row selection integration
  cellSelection: true
};

// With custom styling and interactions
const gridOptions: GridOptions = {
  modules: [RowNumbersModule],
  
  rowNumbers: {
    width: 60,
    onCellClicked: (event) => {
      console.log(`Row ${event.value} clicked`);
    },
    onCellDoubleClicked: (event) => {
      // Custom double-click behavior
      gridApi.selectIndex(event.rowIndex, false, false);
    },
    contextMenuItems: [
      'copy',
      'separator',
      {
        name: 'Select Row',
        action: (params) => {
          params.api.selectIndex(params.node.rowIndex, false, false);
        }
      }
    ]
  }
};

Key Features:

  • Automatic positioning: Always appears as the first (leftmost) column
  • Row selection integration: When cellSelection is enabled, clicking row numbers selects the entire row
  • Row resizing: Optional drag handles for adjusting individual row heights
  • Export support: Can be included in CSV/Excel exports
  • Accessibility: Proper ARIA roles for screen readers
  • Customization: Supports most column definition properties for styling and behavior

Types

// Row grouping types
interface RowGroupingDisplayType {
  singleColumn?: boolean;
  multipleColumns?: boolean;
  groupRows?: boolean;
  custom?: boolean;
}

interface AutoGroupColumnDef extends ColDef {
  headerName?: string;
  field?: string;
  cellRenderer?: string | ICellRendererFunc;
  cellRendererParams?: any;
  valueGetter?: string | ValueGetterFunc;
  keyCreator?: (params: any) => string;
}

// Pivot types
interface PivotColumnGroupDef extends ColGroupDef {
  pivotKeys?: string[];
  pivotTotalColumnIds?: string[];
}

interface ValueColumnDef {
  colId: string;
  aggFunc: string | IAggFunc;
  displayName?: string;
}

// Aggregation types
interface IAggFunc {
  (params: IAggFuncParams): any;
}

interface IAggFuncParams {
  values: any[];
  column: Column;
  colDef: ColDef;
  rowGroupColumns: Column[];
  valueColumns: Column[];
  api: GridApi;
  columnApi: ColumnApi;
}

// Master detail types
interface MasterDetailGridOptions {
  masterDetail?: boolean;
  detailCellRenderer?: string | ICellRendererFunc;
  detailCellRendererParams?: any;
  detailRowHeight?: number;
  detailRowAutoHeight?: boolean;
  keepDetailRows?: boolean;
  keepDetailRowsCount?: number;
}

interface GetDetailRowDataParams {
  node: RowNode;
  data: any;
  successCallback: (rowData: any[]) => void;
}

// Tree data types
interface TreeDataPathParams {
  path: string[];
  level: number;
  parent?: RowNode;
}