AG-Grid React Series #16: Row Selection - Single and Multiple Modes
Welcome back to the AG-Grid React Series! In this installment (#16), we're diving deep into one of the most fundamental and frequently used features of any data grid: row selection.
Whether you need to allow users to pick a single item from a list or select multiple records for a bulk action, AG-Grid provides robust and flexible options for managing row selection with ease in your React applications. We'll explore how to configure both single and multiple row selection, along with essential customization tips.
Prerequisites
Before we begin, ensure you have a basic AG-Grid React setup. This includes having ag-grid-react and ag-grid-community installed and imported into your React component. If you're new, consider reviewing earlier posts in this series for initial setup guidance.
Core Concepts for AG-Grid Row Selection
AG-Grid offers several key properties to control row selection behavior:
rowSelection: This is a grid-level property set on the<AgGridReact />component. It accepts either"single"or"multiple"to define how many rows can be selected at a time.checkboxSelection: A column definition property. Set this totrueon a specific column to display a checkbox within that column's cells, allowing users to select/deselect rows.headerCheckboxSelection: Another column definition property, often used withcheckboxSelection. Set this totrueon a column to display a "select all/none" checkbox in that column's header.onSelectionChanged: A grid event callback. This function is triggered whenever the row selection changes, allowing you to react to user selections.
Implementing Single Row Selection
Single row selection is ideal when users need to pick one item from a list, such as selecting a record to view its details or edit. To enable it:
- Set the
rowSelectionprop on your<AgGridReact />component to"single". - Add
checkboxSelection: trueto one of your column definitions (typically the first column) to provide a visual checkbox for selection.
Code Example: Single Row Selection
Here's how you can set up an AG-Grid instance for single row selection:
import React, { useState, useRef, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';
const SingleSelectionGrid = () => {
const gridRef = useRef(); // Ref for accessing the Grid API
// Sample row data
const [rowData] = useState([
{ make: "Tesla", model: "Model Y", price: 64950, electric: true },
{ make: "Ford", model: "F-Series", price: 33850, electric: false },
{ make: "Toyota", model: "Corolla", price: 29600, electric: false },
{ make: "Mercedes", model: "EQB", price: 54000, electric: true },
]);
// Column Definitions with checkboxSelection for the 'make' column
const [columnDefs] = useState([
{ field: 'make', checkboxSelection: true, flex: 1 },
{ field: 'model', flex: 1 },
{ field: 'price', valueFormatter: p => '£' + p.value.toLocaleString(), flex: 1 },
{ field: 'electric', flex: 1 },
]);
// Callback for when selection changes
const onSelectionChanged = useCallback(() => {
const selectedRows = gridRef.current.api.getSelectedRows();
if (selectedRows.length > 0) {
console.log('Selected single row:', selectedRows[0]);
alert(`Selected: ${selectedRows[0].make} ${selectedRows[0].model}`);
} else {
console.log('No row selected.');
}
}, []);
return (
<div className="ag-theme-quartz" style={{ height: 300, width: '100%' }}>
<h2>Single Row Selection Example</h2>
<AgGridReact
ref={gridRef}
rowData={rowData}
columnDefs={columnDefs}
rowSelection={'single'} // Enable single row selection
onSelectionChanged={onSelectionChanged} // Handle selection changes
/>
</div>
);
};
export default SingleSelectionGrid;
In this example, clicking on a checkbox will select that row and deselect any previously selected row. The onSelectionChanged callback provides immediate feedback in the console and via an alert.
Implementing Multiple Row Selection
Multiple row selection is essential for scenarios like bulk updates, batch deletions, or exporting selected data. To enable it:
- Set the
rowSelectionprop on your<AgGridReact />component to"multiple". - Add
checkboxSelection: trueto one of your column definitions to enable row-level checkboxes. - Optionally, add
headerCheckboxSelection: trueto the same column definition to provide a "select all/none" checkbox in the header. - Consider adding
suppressRowClickSelection={true}to the grid for a more intuitive user experience with multiple checkboxes.
Code Example: Multiple Row Selection
Here's an example demonstrating multiple row selection, including the header checkbox and suppressing row click selection:
import React, { useState, useRef, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';
const MultipleSelectionGrid = () => {
const gridRef = useRef();
const [rowData] = useState([
{ make: "Tesla", model: "Model Y", price: 64950, electric: true },
{ make: "Ford", model: "F-Series", price: 33850, electric: false },
{ make: "Toyota", model: "Corolla", price: 29600, electric: false },
{ make: "Mercedes", model: "EQE", price: 76000, electric: true },
{ make: "Nissan", model: "Qashqai", price: 28000, electric: false },
{ make: "BMW", model: "iX", price: 72000, electric: true },
]);
const [columnDefs] = useState([
{
field: 'make',
checkboxSelection: true,
headerCheckboxSelection: true, // Enables "select all" checkbox in header
flex: 1
},
{ field: 'model', flex: 1 },
{ field: 'price', valueFormatter: p => '£' + p.value.toLocaleString(), flex: 1 },
{ field: 'electric', flex: 1 },
]);
const onSelectionChanged = useCallback(() => {
const selectedRows = gridRef.current.api.getSelectedRows();
console.log('Selected multiple rows:', selectedRows);
// You can perform bulk actions here based on selectedRows
if (selectedRows.length > 0) {
// alert(`Currently selected ${selectedRows.length} rows.`);
} else {
// alert('No rows currently selected.');
}
}, []);
const getSelectedRowsData = useCallback(() => {
const selectedNodes = gridRef.current.api.getSelectedNodes();
const selectedData = selectedNodes.map(node => node.data);
alert(`Selected data: ${JSON.stringify(selectedData, null, 2)}`);
}, []);
return (
<div className="ag-theme-quartz" style={{ height: 350, width: '100%' }}>
<h2>Multiple Row Selection Example</h2>
<button onClick={getSelectedRowsData} style={{ marginBottom: 10, padding: '8px 15px', cursor: 'pointer' }}>
Get Selected Rows Data
</button>
<AgGridReact
ref={gridRef}
rowData={rowData}
columnDefs={columnDefs}
rowSelection={'multiple'} // Enable multiple row selection
onSelectionChanged={onSelectionChanged}
suppressRowClickSelection={true} // Prevents row click from selecting, requires checkbox
/>
</div>
);
};
export default MultipleSelectionGrid;
With rowSelection={'multiple'}, users can select multiple rows by clicking their checkboxes. The headerCheckboxSelection: true adds a convenient "select all/none" checkbox in the header. Notice the use of suppressRowClickSelection={true}. This property is crucial for a cleaner user experience with checkbox selection, as it ensures that clicking anywhere on a row (other than the checkbox) does not affect its selection state. Users must explicitly click the checkbox.
Advanced Row Selection Options and Best Practices
Suppressing Row Click Selection
As mentioned, suppressRowClickSelection={true} disables the default behavior where clicking on a row selects it. This is highly recommended when you're using checkboxSelection, especially with multiple selection, to avoid confusing users who might accidentally select rows by clicking them instead of using the designated checkboxes.
<AgGridReact
// ... other props
rowSelection={'multiple'}
suppressRowClickSelection={true} // Ensures only checkboxes control selection
/>
Conditional Row Selection with isRowSelectable
Sometimes, you might have business rules that prevent certain rows from being selected. AG-Grid provides the isRowSelectable grid property, which is a callback function that takes a rowNode and returns a boolean:
- Return
trueif the row can be selected. - Return
falseif the row should not be selectable.
const isRowSelectable = useCallback((rowNode) => {
// Only allow electric cars to be selected
return rowNode.data.electric === true;
}, []);
// ... in your AgGridReact component
<AgGridReact
// ... other props
isRowSelectable={isRowSelectable}
/>
When a row is not selectable, its checkbox will be disabled, and it cannot be selected programmatically or via the header checkbox.
Programmatic Row Selection
You can also control row selection directly using the Grid API. The most common methods are:
api.getSelectedRows(): Returns an array of the data for all selected rows.api.getSelectedNodes(): Returns an array of the Row Nodes for all selected rows. Row Nodes provide more information and methods (e.g.,rowNode.setSelected(true/false)).rowNode.setSelected(true/false, clearOtherSelections): Directly sets the selection state of a specific row node. The optionalclearOtherSelections(default `false`) determines if other selected rows should be deselected.
To access these, you typically use a ref attached to your <AgGridReact /> component:
// To select the first row programmatically
const selectFirstRow = useCallback(() => {
gridRef.current.api.forEachNode((node, index) => {
if (index === 0) {
node.setSelected(true); // Selects the first row
} else {
node.setSelected(false); // Deselects others
}
});
}, []);
// To deselect all rows
const deselectAll = useCallback(() => {
gridRef.current.api.deselectAll();
}, []);
Conclusion
Row selection is a cornerstone feature for interactive data grids, and AG-Grid for React makes it incredibly straightforward to implement both single and multiple selection modes. By leveraging the rowSelection, checkboxSelection, headerCheckboxSelection, and advanced options like suppressRowClickSelection and isRowSelectable, you gain fine-grained control over the user experience and can seamlessly integrate selection logic into your React applications.
Experiment with these properties to provide your users with an intuitive and powerful way to interact with their data.
```