Advanced row manipulation including grouping, pivoting, aggregation, master-detail functionality, and tree data operations for comprehensive data organization and analysis.
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);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);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"
}
];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
};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("/"));
}
});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:
cellSelection is enabled, clicking row numbers selects the entire row// 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;
}