React Data Grid
ApexGrid works with React as a web component. The @lit/react package provides a wrapper that bridges Lit events to React's synthetic event system.
Installation
npm install apex-grid @lit/react
@lit/react is the current package name. The older @lit-labs/react was the preview name and is now deprecated.
Create a typed wrapper
Use createComponent from @lit/react to wrap the element. The factory function pattern below preserves the TypeScript generics on the grid's data and columns props.
// apex-grid-wrapper.tsx
import React from 'react'
import { createComponent } from '@lit/react'
import { ApexGrid, ColumnConfiguration } from 'apex-grid'
ApexGrid.register()
export function createApexGrid<T extends object>() {
return createComponent({
tagName: 'apex-grid',
elementClass: ApexGrid<T>,
react: React,
events: {
onRowSelected: 'rowSelected',
onRowSelecting: 'rowSelecting',
onCellValueChanged: 'cellValueChanged',
onFiltered: 'filtered',
onSorted: 'sorted',
onPageChanged: 'pageChanged',
},
})
}
Usage
Call the factory once per data type at module scope, then use the resulting component like any React component.
// App.tsx
import { createApexGrid } from './apex-grid-wrapper'
import { ColumnConfiguration } from 'apex-grid'
interface User {
id: number
name: string
email: string
}
const UserGrid = createApexGrid<User>()
export default function App() {
const data: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]
const columns: ColumnConfiguration<User>[] = [
{ key: 'id', headerText: 'ID', type: 'number' },
{ key: 'name', headerText: 'Name', sort: true, filter: true },
{ key: 'email', headerText: 'Email', sort: true },
]
return (
<UserGrid
data={data}
columns={columns}
onRowSelected={(e) => console.log('selected:', e.detail)}
/>
)
}
Imperative access
Use a ref to call grid methods directly. Pass the ref to the wrapped component using the standard React ref prop.
import { useRef, useEffect } from 'react'
import { createApexGrid } from './apex-grid-wrapper'
import { ApexGrid, ColumnConfiguration } from 'apex-grid'
interface User {
id: number
name: string
email: string
}
const UserGrid = createApexGrid<User>()
export default function App() {
const gridRef = useRef<ApexGrid<User>>(null)
const data: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]
const columns: ColumnConfiguration<User>[] = [
{ key: 'id', headerText: 'ID', type: 'number' },
{ key: 'name', headerText: 'Name', sort: true },
{ key: 'email', headerText: 'Email' },
]
useEffect(() => {
gridRef.current?.sort({ key: 'name', direction: 'ascending' })
}, [])
return (
<UserGrid
ref={gridRef}
data={data}
columns={columns}
/>
)
}
Available events
The events map passed to createComponent controls which custom events become React props: add an onX: 'domEventName' entry for each event you want to handle (the example above wires the six most common). ApexGrid dispatches the following events.
Events emitted before an operation (the -ing / -Changing variants) are cancellable: call e.detail's cancellation or e.preventDefault() to stop the operation, and you can modify the expression before it runs.
| Suggested prop | DOM event | Cancellable | Fires |
|---|---|---|---|
onRowSelecting | rowSelecting | yes | Before the row selection set changes |
onRowSelected | rowSelected | After row selection changes | |
onCellValueChanging | cellValueChanging | yes | Before a cell value is committed |
onCellValueChanged | cellValueChanged | After a cell value is committed | |
onCellValidationFailed | cellValidationFailed | A candidate cell value was rejected by validators | |
onRowEditStarted | rowEditStarted | A row entered edit mode (row edit mode) | |
onRowEditEnded | rowEditEnded | A row left edit mode (committed reports whether it saved) | |
onSorting | sorting | yes | Before a sort is applied |
onSorted | sorted | After a sort is applied | |
onFiltering | filtering | yes | Before a filter is applied |
onFiltered | filtered | After a filter is applied | |
onQuickFilterChanging | quickFilterChanging | yes | Before the quick-filter value is applied |
onQuickFilterChanged | quickFilterChanged | After the quick filter is applied | |
onPageChanging | pageChanging | yes | Before a page or page-size change |
onPageChanged | pageChanged | After a page or page-size change | |
onColumnPinning | columnPinning | yes | Before a column's pin position changes |
onColumnPinned | columnPinned | After a column's pin position changes | |
onColumnMoving | columnMoving | yes | Before a column moves |
onColumnMoved | columnMoved | After a column moves | |
onRowPinning | rowPinning | yes | Before a row is pinned, moved between bands, or unpinned |
onRowPinned | rowPinned | After a row's pin state changes | |
onRowMoving | rowMoving | yes | Before a row moves |
onRowMoved | rowMoved | After a row moves | |
onRowExpanding | rowExpanding | yes | Before the row-expansion set changes |
onRowExpanded | rowExpanded | After a row-expansion change | |
onTreeRowExpanding | treeRowExpanding | yes | Before the tree-row expansion set changes |
onTreeRowExpanded | treeRowExpanded | After a tree-row expansion change | |
onHistoryChanged | historyChanged | After the undo / redo stacks change | |
onStateChanged | stateChanged | After the grid's state changes (debounced) |
Each handler receives the CustomEvent; read e.detail for the payload (typed per event, e.g. ApexRowSelectedEvent<T>, SortExpression<T>).