Selection & Events
ReoGrid Web provides a full set of APIs for working with cell selection, subscribing to events, controlling scroll position, and performing hit testing.
Live Demo
Selection Range Operations
worksheet.selection returns a SelectionHandle — a thin façade over the active selection that exposes both reads (bounds, active cell, range view) and mutations (style operations, value, move).
const ws = grid.worksheet
// Move the selection — numeric coordinates
ws.selection.moveTo(0, 0, 4, 3) // topRow, leftColumn, bottomRow, rightColumn
// Or by A1-style address
ws.selection.moveTo('A1:D5')
// Read current bounds (null when nothing is selected)
const b = ws.selection.bounds
if (b) {
console.log(b.topRow, b.leftColumn, b.bottomRow, b.rightColumn)
}
// Active (focused) cell within the selection
const active = ws.selection.activeCell // { row, column } | null
// Convert the selection to a RangeHandle for full range operations
const range = ws.selection.range
range?.setBold().setBackgroundColor('#fef3c7')
// Check whether a given cell is the active one
const isActive = ws.isActiveCell(0, 0)
An internal
SelectionRangestate machine backs the handle, but it is@internaland is not part of the public API. Always useworksheet.selection.
Events
All event methods return an unsubscribe function.
Selection Change
const unsub = ws.onSelectionChange((cell) => {
if (cell) {
const col = String.fromCharCode(65 + cell.column)
console.log(`Selected: ${col}${cell.row + 1}`)
}
})
// Unsubscribe
unsub()
Cell Value Change
ws.onCellValueChange(({ row, column }) => {
console.log(`Cell changed: row=${row}, col=${column}`)
const value = ws.getCellInput(row, column)
console.log('New value:', value)
})
Context Menu
ws.onContextMenu((event) => {
// event.area: 'cells' | 'row-header' | 'column-header'
// event.row, event.column: click position
// event.originalEvent: browser MouseEvent
console.log('Context menu:', event.area, event.row, event.column)
})
Viewport Size Change
ws.onViewportSizeChange(({ width, height }) => {
console.log(`Viewport resized: ${width} x ${height}`)
})
Scroll Change
ws.onScrollChange(({ x, y }) => {
console.log(`Scroll position: x=${x}, y=${y}`)
})
Structure Change (Row/Column Insert/Delete)
ws.onStructureChange(() => {
console.log('Grid structure changed')
})
Image Change
ws.onImagesChange((images) => {
console.log('Images updated:', images.length)
})
Protected Cell Edit Attempt
ws.onProtectedCellEdit(({ row, column }) => {
alert(`Cell (${row}, ${column}) is protected`)
})
Scroll Operations
// Get scroll position
const offset = ws.getScrollOffset()
console.log(offset.x, offset.y)
// Set scroll position
ws.setScrollOffset(100, 200)
// Scroll content size
const size = ws.getScrollContentSize()
console.log(size.width, size.height)
// Viewport size
const bodyWidth = ws.getBodyViewportWidth()
const bodyHeight = ws.getBodyViewportHeight()
Hit Testing
Identify a cell position from screen coordinates.
// Simple hit test
const cell = ws.getCellFromPoint(x, y)
if (cell) {
console.log(`Row: ${cell.row}, Column: ${cell.column}`)
}
// Detailed hit test
const result = ws.hitTest(x, y)
Getting Cell Rectangles
// Get cell rectangle on screen
const rect = ws.getCellRect(0, 0)
// { x, y, width, height }
// Get range rectangle on screen
const rangeRect = ws.getRangeRect(0, 0, 4, 3)
Example: Toolbar Integration
import { useState } from 'react'
function Toolbar({ worksheet }) {
const [cellRef, setCellRef] = useState('A1')
const [cellValue, setCellValue] = useState('')
useEffect(() => {
if (!worksheet) return
return worksheet.onSelectionChange((cell) => {
if (cell) {
const col = String.fromCharCode(65 + cell.column)
setCellRef(`${col}${cell.row + 1}`)
setCellValue(worksheet.getCellInput(cell.row, cell.column) || '')
}
})
}, [worksheet])
return (
<div>
<span>{cellRef}</span>
<input
value={cellValue}
onChange={(e) => {
setCellValue(e.target.value)
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
const active = worksheet.selection.activeCell
if (active) {
worksheet.setCellInput(active.row, active.column, cellValue)
}
}
}}
/>
</div>
)
}