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

selection-interaction.mddocs/

Selection and Interaction

Enhanced selection capabilities including range selection, cell selection, clipboard operations, and advanced user interaction features for comprehensive grid manipulation.

Capabilities

Range Selection

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();

Cell Selection

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}`);
});

Fill Handle

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");
  }
};

Keyboard Navigation

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");
}

Context Menu

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;
  }
};

Types

// 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;
}