Enhanced selection capabilities including range selection, cell selection, clipboard operations, and advanced user interaction features for comprehensive grid manipulation.
Multi-cell range selection with support for complex selection operations and range manipulation.
/**
* Range selection service for multi-cell operations
*/
interface IRangeService {
/** Get all current cell ranges */
getCellRanges(): CellRange[] | null;
/** Add a new cell range */
addCellRange(params: CellRangeParams): void;
/** Clear all selections */
clearSelection(): void;
/** Remove range by ID */
removeRange(range: CellRange): void;
/** Check if range selection is enabled */
isRangeSelectionEnabled(): boolean;
}
/**
* Cell range definition
*/
interface CellRange {
/** Unique range ID */
id?: string;
/** Range type */
type?: string;
/** Starting row index */
startRow?: RowPosition;
/** Ending row index */
endRow?: RowPosition;
/** Starting column */
startColumn: Column;
/** Ending column */
endColumn: Column;
}
/**
* Parameters for creating cell ranges
*/
interface CellRangeParams {
/** Starting row index */
rowStartIndex?: number;
/** Ending row index */
rowEndIndex?: number;
/** Starting row pinned position */
rowStartPinned?: string;
/** Ending row pinned position */
rowEndPinned?: string;
/** Starting column key or instance */
columnStart?: string | Column;
/** Ending column key or instance */
columnEnd?: string | Column;
}
/**
* Row position definition
*/
interface RowPosition {
/** Row index */
rowIndex: number;
/** Pinned position */
rowPinned?: string;
}Usage Example:
import { RangeSelectionModule } from "ag-grid-enterprise";
const gridOptions: GridOptions = {
modules: [RangeSelectionModule],
enableRangeSelection: true,
enableRangeHandle: true,
enableFillHandle: true,
// Range selection events
onRangeSelectionChanged: (event) => {
const ranges = gridApi.getCellRanges();
console.log(`Selected ${ranges?.length || 0} ranges`);
}
};
// Programmatic range selection
const rangeService = gridApi.getRangeService();
// Select a range of cells
rangeService.addCellRange({
rowStartIndex: 0,
rowEndIndex: 4,
columnStart: "athlete",
columnEnd: "country"
});
// Select multiple ranges
rangeService.addCellRange({
rowStartIndex: 10,
rowEndIndex: 15,
columnStart: "gold",
columnEnd: "total"
});
// Get all current ranges
const currentRanges = rangeService.getCellRanges();
if (currentRanges) {
currentRanges.forEach((range, index) => {
console.log(`Range ${index}: from ${range.startColumn.getColId()} to ${range.endColumn.getColId()}`);
});
}
// Clear all selections
rangeService.clearSelection();Individual cell selection with support for single and multiple cell operations.
/**
* Cell selection API for individual cell operations
*/
interface ICellSelectionService {
/** Select a specific cell */
selectCell(params: CellSelectionParams): void;
/** Select multiple cells */
selectCells(params: CellSelectionParams[]): void;
/** Clear cell selections */
clearCellSelection(): void;
/** Get selected cells */
getSelectedCells(): CellPosition[];
/** Check if cell is selected */
isCellSelected(params: CellPosition): boolean;
}
/**
* Cell selection parameters
*/
interface CellSelectionParams {
/** Row index */
rowIndex: number;
/** Column key or instance */
column: string | Column;
/** Pinned row position */
rowPinned?: string;
/** Whether to focus the cell */
floating?: string;
}
/**
* Cell position definition
*/
interface CellPosition {
/** Row index */
rowIndex: number;
/** Column instance */
column: Column;
/** Pinned position */
rowPinned?: string;
}Usage Example:
import { CellSelectionModule } from "ag-grid-enterprise";
const gridOptions: GridOptions = {
modules: [CellSelectionModule],
rowSelection: "multiple",
suppressRowClickSelection: true, // Disable row selection to focus on cell selection
onCellClicked: (event) => {
console.log(`Cell clicked: ${event.column.getColId()} at row ${event.rowIndex}`);
}
};
// Select specific cell
gridApi.selectCell({
rowIndex: 0,
column: "athlete"
});
// Select multiple cells
gridApi.selectCells([
{ rowIndex: 0, column: "athlete" },
{ rowIndex: 1, column: "country" },
{ rowIndex: 2, column: "gold" }
]);
// Check if cell is selected
const isSelected = gridApi.isCellSelected({
rowIndex: 0,
column: gridApi.getColumn("athlete")
});
// Get all selected cells
const selectedCells = gridApi.getSelectedCells();
selectedCells.forEach(cell => {
console.log(`Selected: ${cell.column.getColId()} at row ${cell.rowIndex}`);
});Drag-to-fill functionality for extending data patterns across cells.
/**
* Fill handle configuration for drag-to-fill operations
*/
interface FillHandleOptions {
/** Enable fill handle */
enableFillHandle?: boolean;
/** Fill operation callback */
fillOperation?: (params: FillOperationParams) => any;
/** Custom fill handle direction */
direction?: "x" | "y" | "xy";
}
/**
* Fill operation parameters
*/
interface FillOperationParams {
/** Current value being filled */
currentValue: any;
/** Current row node */
currentRowNode: RowNode;
/** Current column */
currentColumn: Column;
/** Direction of fill */
direction: "up" | "down" | "left" | "right";
/** Values in the fill range */
values: any[];
/** Initial range that was selected */
initialRange: CellRange;
/** Final range after fill */
endRange: CellRange;
}Usage Example:
const gridOptions: GridOptions = {
enableRangeSelection: true,
enableFillHandle: true,
// Custom fill operation
fillOperation: (params) => {
const { currentValue, direction, values } = params;
// Custom logic for different column types
if (params.currentColumn.getColId() === "sequence") {
// Auto-increment sequence
const lastValue = values[values.length - 1];
return typeof lastValue === "number" ? lastValue + 1 : 1;
}
if (params.currentColumn.getColId() === "date") {
// Increment dates by one day
const date = new Date(currentValue);
date.setDate(date.getDate() + 1);
return date;
}
// Default behavior - copy value
return currentValue;
},
onFillStart: (event) => {
console.log("Fill operation started");
},
onFillEnd: (event) => {
console.log("Fill operation completed");
}
};Enhanced keyboard navigation with customizable shortcuts and navigation behavior.
/**
* Navigation service for keyboard operations
*/
interface INavigationService {
/** Navigate to next cell */
navigateToNextCell(event: KeyboardEvent): void;
/** Navigate to next header */
navigateToNextHeader(event: KeyboardEvent): void;
/** Get next focusable cell */
getNextFocusableCell(params: GetNextFocusableCellParams): CellPosition | null;
}
/**
* Parameters for getting next focusable cell
*/
interface GetNextFocusableCellParams {
/** Current cell position */
currentCell: CellPosition;
/** Direction to navigate */
direction: "up" | "down" | "left" | "right";
/** Whether to allow header navigation */
allowHeaderNavigation?: boolean;
}
/**
* Custom keyboard navigation parameters
*/
interface NavigationParams {
/** Previous cell position */
previousCellPosition: CellPosition | null;
/** Next cell position to navigate to */
nextCellPosition: CellPosition | null;
/** The keyboard event */
event: KeyboardEvent | null;
}Usage Example:
const gridOptions: GridOptions = {
// Enable keyboard navigation
suppressKeyboardEvent: (params) => {
// Custom keyboard handling
const event = params.event;
const key = event.key;
// Custom Ctrl+D for fill down
if (event.ctrlKey && key === "d") {
gridApi.copyRangeDown();
return true; // Suppress default behavior
}
// Custom Ctrl+Shift+Arrow for range selection
if (event.ctrlKey && event.shiftKey &&
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(key)) {
// Custom range selection logic
return false; // Allow default behavior
}
return false; // Allow default keyboard behavior
},
// Custom tab navigation
tabToNextCell: (params) => {
const nextCell = params.nextCellPosition;
const previousCell = params.previousCellPosition;
// Skip read-only columns during tab navigation
if (nextCell && nextCell.column.getColDef().editable === false) {
// Find next editable cell
return {
rowIndex: nextCell.rowIndex,
column: gridApi.getColumns()?.find(col => col.getColDef().editable !== false)
};
}
return nextCell;
},
// Custom navigation behavior
navigateToNextCell: (params) => {
// Custom navigation logic
return params.nextCellPosition;
}
};
// Programmatic navigation
const currentCell = gridApi.getFocusedCell();
if (currentCell) {
// Navigate to cell below
gridApi.setFocusedCell(currentCell.rowIndex + 1, currentCell.column);
// Navigate to specific cell
gridApi.setFocusedCell(5, "athlete");
}Enhanced context menu with custom actions and enterprise-specific options.
/**
* Context menu configuration
*/
interface GetContextMenuItemsParams {
/** Default menu items */
defaultItems: (string | MenuItemDef)[];
/** Current column */
column?: Column;
/** Current row node */
node?: RowNode;
/** Current value */
value?: any;
/** Grid API */
api: GridApi;
/** Column API */
columnApi: ColumnApi;
/** Grid context */
context?: any;
}
/**
* Menu item definition
*/
interface MenuItemDef {
/** Menu item name/key */
name: string;
/** Display name */
displayName?: string;
/** Icon class or HTML */
icon?: string;
/** Action function */
action?: (params?: any) => void;
/** Whether item is disabled */
disabled?: boolean;
/** Submenu items */
subMenu?: (string | MenuItemDef)[];
/** CSS class */
cssClasses?: string[];
/** Tooltip text */
tooltip?: string;
}Usage Example:
const gridOptions: GridOptions = {
getContextMenuItems: (params) => {
const result: (string | MenuItemDef)[] = [
// Default items
"copy",
"copyWithHeaders",
"paste",
"separator",
"export",
"separator",
// Custom items
{
name: "highlight",
displayName: "Highlight Row",
icon: '<i class="fa fa-star"/>',
action: () => {
if (params.node) {
// Custom highlighting logic
params.node.setSelected(true);
console.log("Row highlighted");
}
}
},
{
name: "analytics",
displayName: "Analytics",
subMenu: [
{
name: "sum",
displayName: "Sum Column",
action: () => {
// Calculate sum for selected column
if (params.column) {
const sum = gridApi.getDisplayedRowCount();
console.log(`Sum: ${sum}`);
}
}
},
{
name: "average",
displayName: "Average",
action: () => {
// Calculate average
console.log("Calculate average");
}
}
]
}
];
return result;
}
};// Range selection types
interface CellRange {
id?: string;
type?: string;
startRow?: RowPosition;
endRow?: RowPosition;
startColumn: Column;
endColumn: Column;
}
interface RowPosition {
rowIndex: number;
rowPinned?: string;
}
// Cell position interface
interface CellPosition {
rowIndex: number;
column: Column;
rowPinned?: string;
}
// Fill operation types
interface FillOperationParams {
currentValue: any;
currentRowNode: RowNode;
currentColumn: Column;
direction: "up" | "down" | "left" | "right";
values: any[];
initialRange: CellRange;
endRange: CellRange;
}
// Navigation parameters
interface NavigationParams {
previousCellPosition: CellPosition | null;
nextCellPosition: CellPosition | null;
event: KeyboardEvent | null;
}
// Context menu types
interface GetContextMenuItemsParams {
defaultItems: (string | MenuItemDef)[];
column?: Column;
node?: RowNode;
value?: any;
api: GridApi;
columnApi: ColumnApi;
context?: any;
}
interface MenuItemDef {
name: string;
displayName?: string;
icon?: string;
action?: (params?: any) => void;
disabled?: boolean;
subMenu?: (string | MenuItemDef)[];
cssClasses?: string[];
tooltip?: string;
}