Cell Selection
To use multi-cell selection, you need to configure the <DataSource />
component with selectionMode="multi-cell"
- see selectionMode
for details. For selecting rows, see the Row Selection page.
<DataSource selectionMode="multi-cell" />
// can be "single-row", "multi-row", "multi-cell" or false
Click cells in the grid to add to the selection.
Use Shift+Click
to select a range of cells and Cmd/Ctrl+Click
to add single cells to the selection.
import { InfiniteTable, DataSource, InfiniteTablePropColumns, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/developers1k') .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', defaultWidth: 60 }, firstName: { field: 'firstName' }, preferredLanguage: { field: 'preferredLanguage' }, stack: { field: 'stack' }, country: { field: 'country' }, age: { field: 'age', type: 'number' }, salary: { field: 'salary', type: 'number' }, currency: { field: 'currency', type: 'number' }, }; export default function App() { return ( <DataSource<Developer> primaryKey="id" data={dataSource} selectionMode="multi-cell" > <InfiniteTable<Developer> columns={columns} columnDefaultWidth={100} /> </DataSource> ); }
Using default selection
You can specify a default value for cell selection by using the defaultCellSelection
prop.
const defaultCellSelection = {
defaultSelection: false,
selectedCells: [
[3, "stack"], // rowId + colId
[5, "stack"], // rowId + colId
[0, "firstName"], // rowId + colId
]
}
<DataSource
selectionMode="multi-cell"
defaultCellSelection={defaultCellSelection}
Note
Cell selection uses [rowId, colId]
cell descriptors to identify cells to be marked as selected or deselected - read more in the Cell selection format.
By default some cells are already selected in the grid below, by using the defaultCellSelection
prop on the <DataSource />
component.
import { InfiniteTable, DataSource, InfiniteTablePropColumns, DataSourcePropCellSelection_MultiCell, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/developers1k') .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', defaultWidth: 60 }, firstName: { field: 'firstName' }, preferredLanguage: { field: 'preferredLanguage' }, stack: { field: 'stack' }, country: { field: 'country' }, age: { field: 'age', type: 'number' }, salary: { field: 'salary', type: 'number' }, currency: { field: 'currency', type: 'number' }, }; export default function App() { const defaultCellSelection: DataSourcePropCellSelection_MultiCell = { defaultSelection: false, selectedCells: [ [3, 'stack'], // rowId + colId [4, 'stack'], [5, 'stack'], [0, 'firstName'], ], }; return ( <DataSource<Developer> primaryKey="id" data={dataSource} defaultCellSelection={defaultCellSelection} selectionMode="multi-cell" > <InfiniteTable<Developer> columns={columns} columnDefaultWidth={100} /> </DataSource> ); }
Whe you're using cell selection with or without any default value (via the defaultCellSelection
), you're using an uncontrolled prop. This means that the selection state is managed by the <DataSource />
component and not by you. If you want to control the selection state yourself, you can use the controlled cellSelection
prop instead - see Using controlled selection for details.
Cell selection format
The cellSelection
prop is an object with the following shape:
defaultSelection
-boolean
- whether or not cells are selected by default.- either:
selectedCells
:[rowId, colId][]
- an array of cells that should be selected (this is combined withdefaultSelection: false
)
- or
deselectedCells
:[rowId, colId][]
- an array of cells that should be deselected (this is combined withdefaultSelection: true
)
Note
When defaultSelection
is true
, you will only need to specify the deselectedCells
prop.
And when defaultSelection
is false
, you will only need to specify the selectedCells
prop.
In this way, you can either specify which cells should be selected or which cells should be deselected - and have a default that matches the most common case.
Note
The selectedCells
/deselectedCells
are arrays of [rowId, colId]
tuples. The rowId
is the id
of the row (the primary key), and the colId
is the id
of the column (the identifier of the column in the columns
prop).
The following scenarios are all possible:
const defaultCellSelection = {
defaultSelection: false,
selectedCells: [
['id2', 'stack'],
['id2', 'stack'],
['id0', 'firstName'],
],
};
const defaultCellSelection = {
defaultSelection: true,
deselectedCells: [
['row2', 'stack'],
['row3', 'stack'],
['row5', 'firstName'],
],
};
Using wildcards for selection
It's also possible to use wildcards for selecting cells. This is useful if you want to select all cells in a column, or all cells in a row.
const defaultCellSelection = {
defaultSelection: false,
selectedCells: [
['*', 'stack'],
['row2', 'firstName'],
],
};
const defaultCellSelection = {
defaultSelection: false,
selectedCells: [
['row1', '*'],
['row2', 'firstName'],
],
};
const defaultCellSelection = {
defaultSelection: true,
deselectedCells: [['*', 'stack']],
};
Using controlled selection
When using the controlled cellSelection
you have to update the value of the property yourself, by listening to the onCellSelectionChange
event.
This example shows how to use the onCellSelectionChange
callback prop to listen to changes to the controlled cellSelection
prop on the <DataSource />
component.
import { InfiniteTable, DataSource, InfiniteTablePropColumns, DataSourcePropCellSelection_MultiCell, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/developers1k') .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', defaultWidth: 60 }, firstName: { field: 'firstName' }, preferredLanguage: { field: 'preferredLanguage' }, stack: { field: 'stack' }, country: { field: 'country' }, age: { field: 'age', type: 'number' }, salary: { field: 'salary', type: 'number' }, currency: { field: 'currency', type: 'number' }, }; export default function App() { const [cellSelection, setCellSelection] = React.useState<DataSourcePropCellSelection_MultiCell>({ defaultSelection: false, selectedCells: [ [3, 'stack'], [0, 'firstName'], ], }); return ( <div style={{ display: 'flex', flex: 1, color: 'var(--infinite-cell-color)', flexFlow: 'column', background: 'var(--infinite-background)', }} > <div style={{ maxHeight: 200, overflow: 'auto', border: '2px solid magenta', }} > Current selection: <pre>{JSON.stringify(cellSelection, null, 2)}</pre> </div> <DataSource<Developer> primaryKey="id" data={dataSource} cellSelection={cellSelection} onCellSelectionChange={setCellSelection} selectionMode="multi-cell" > <InfiniteTable<Developer> columns={columns} columnDefaultWidth={100} /> </DataSource> </div>
Using the Cell Selection API
The <DataSource />
component also exposes a Cell Selection API, which you can use to select and deselect cells programmatically.
import { InfiniteTable, DataSource, InfiniteTablePropColumns, DataSourcePropCellSelection_MultiCell, InfiniteTableApi, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/developers1k') .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', defaultWidth: 60 }, firstName: { field: 'firstName' }, preferredLanguage: { field: 'preferredLanguage' }, stack: { field: 'stack' }, country: { field: 'country' }, age: { field: 'age', type: 'number' }, salary: { field: 'salary', type: 'number' }, currency: { field: 'currency', type: 'number' }, }; export default function App() { const [cellSelection, setCellSelection] = React.useState<DataSourcePropCellSelection_MultiCell>({ defaultSelection: false, selectedCells: [ [3, 'stack'], [0, 'firstName'], ], }); const [api, setApi] = React.useState<InfiniteTableApi<Developer> | null>(); return ( <div style={{ display: 'flex', flex: 1, color: 'var(--infinite-cell-color)', flexFlow: 'column', background: 'var(--infinite-background)', }} > <button style={{ margin: 10, padding: 10, borderRadius: 5, border: '2px solid magenta', }} onClick={() => { api?.cellSelectionApi.selectColumn('firstName'); }} > Select "firstName" column </button> <div style={{ maxHeight: 200, overflow: 'auto', border: '2px solid magenta', }} > Current selection: <pre>{JSON.stringify(cellSelection, null, 2)}</pre> </div> <DataSource<Developer> primaryKey="id" data={dataSource} cellSelection={cellSelection} onCellSelectionChange={setCellSelection} selectionMode="multi-cell" > <InfiniteTable<Developer> columns={columns} columnDefaultWidth={100} onReady={({ api }) => { setApi(api); }} /> </DataSource> </div>