Selection in Flutter DataGrid (SfDataGrid)
12 Mar 202424 minutes to read
This section explains how to enable selection in the Datagrid; modes, properties, and callbacks involved in selection and customizations available for selection.
The Datagrid allows you to select a specific row or group of rows either programmatically or by touch interactions. To enable selection, set the selectionMode property of the SfDataGrid to a value other than none
. SfDataGrid has different selection modes to perform the selection operation as follows.
NOTE
The rows property must be initialized in the source. The
rows
is the collection ofDataGridRow
to populate the rows in DataGrid.
Selection modes
Modes | Description |
---|---|
none | Disables selection and no rows can be selected. This is the default value. |
single | Allows selection of a single row only. Upon selecting the next row, the selection in the previous row is cleared. |
multiple | Allows selection of more than one row. Selection is not cleared when selecting more than one row. When you click on a selected row for the second time, the selection is cleared. |
singleDeselect | Allows selection of only a single row. However, upon tapping the row again, the selection is cleared. Similar to single mode, upon selecting the next row, the selection in the previous row is cleared. |
Current cell navigation
Keyboard navigation through the cells and rows is determined based on the navigationMode property. The GridNavigationMode.cell
allows you to navigate between the cells in a row and between the rows. The GridNavigationMode.row
allows you to navigate between the rows.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.cell,
),
);
}
Single row selection
It allows you to select only one row. For example, you have selected a row. Now if you select some other row, the previous row selection will be cleared. Hence it is a single
row selection mode.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.single));
}
Multiple row selection
The SfDataGrid allows you to select multiple rows by setting the selectionMode
property as multiple,
where you can select multiple rows by clicking on SfDataGrid and also using the key modifiers.
While using multiple
, you can select multiple rows by pressing the key modifiers Shift + Down and Shift + Up.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple));
}
NOTE
When the
selectionMode
ismultiple
, multiple rows can be selected or deselected by clicking the respective rows. In multiple selections, pressing the navigation keys will move the current cell alone. The rows can be selected or deselected by pressing the Space key.
Disable selection
The selection can be disabled by setting the selectionMode
property as none
.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.none));
}
Selection on a particular row can be disabled by handling the onCurrentCellActivating callback.
NOTE
You cannot select the header row of SfDataGrid.
Getting selected rows
Get the information of the selected rows by using the controller property. Create an instance of the DataGridController and set it to controller property. The selectedRow property returns the selected DataGridRow and the selectedIndex property returns the index of the selectedRow in SfDataGrid. The selectedRow denotes the last selected row in multiple selections.
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Get Selection Information'),
onPressed: () {
//SelectedIndex
var _selectedIndex = _dataGridController.selectedIndex;
//SelectedRow
var _selectedRow = _dataGridController.selectedRow;
//SelectedRows
var _selectedRows = _dataGridController.selectedRows;
print(_selectedIndex);
print(_selectedRow);
print(_selectedRows);
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.multiple))
]));
}
NOTE
DataGridController objects are expected to be long-lived, not re-created with each build.
Programmatic selection
When selectionMode
is set to a value other than none
, the selected rows from the code by setting the DataGridController.selectedIndex
, DataGridController.selectedRow
, or DataGridController.selectedRows
property based on the selection mode.
When the selection mode is single
, programmatically select a row in two ways either by setting the row index to the DataGridController.selectedIndex
property, or by setting the DataGridRow
to be selected to the DataGridController.selectedRow
property
The following code example shows how to select a row using selectedIndex
,
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Set Selection'),
onPressed: () {
//SelectedIndex
_dataGridController.selectedIndex = 4;
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.single))
]));
}
The following code example shows how to select a row using selectedRow
,
late EmployeeDataSource _employeeDataSource;
final DataGridController _dataGridController = DataGridController();
List<Employee> _employees = <Employee>[];
@override
void initState() {
super.initState();
_employees = getEmployeeData();
_employeeDataSource = EmployeeDataSource(employees: _employees);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Set Selection'),
onPressed: () {
//SelectedRow
_dataGridController.selectedRow = _employeeDataSource.dataGridRows[3];
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.single))
]));
}
Multiple rows can be selected by adding a collection of DataGridRow
to the selectedRows
property.
late EmployeeDataSource _employeeDataSource;
final DataGridController _dataGridController = DataGridController();
List<Employee> _employees = <Employee>[];
@override
void initState() {
super.initState();
_employees = getEmployeeData();
_employeeDataSource = EmployeeDataSource(employees: _employees);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Set Selection'),
onPressed: () {
//SelectedRows
_dataGridController.selectedRows = [
_employeeDataSource.dataGridRows[1],
_employeeDataSource.dataGridRows[3],
_employeeDataSource.dataGridRows[6],
];
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.multiple))
]));
}
Get the current cell
The current cell information such as row index, and column index can be retrieved using the currentCell property of DataGridController.
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Get current cell'),
onPressed: () {
var _currentCell = _dataGridController.currentCell;
print(_currentCell);
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.cell))
]));
}
Process current cell
The CurrentCell can be moved to a particular cell by using the moveCurrentCellTo method in DataGridController
.
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Move current cell'),
onPressed: () {
_dataGridController.moveCurrentCellTo(RowColumnIndex(6, 3));
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.cell))
]));
}
Clear selection
DataGrid allows you to clear the selection applied in the grid rows by setting the DataGridController.selectedIndex
to -1
or DataGridController.selectedRow
to null when the selectionMode
property is in single
or singleDeselect.
When the selectionMode property is in multiple,
clear the selection from grid rows by setting the DataGridController.selectedRows
to empty.
The following code example shows how to clear selection when the selectionMode
property is in single
or singleDeselect.
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Clear Selection'),
onPressed: () {
_dataGridController.selectedIndex = -1;
//or
//this._dataGridController.selectedRow = null;
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.single))
]));
}
The following code example shows how to clear selection when the selectionMode
property is in multiple.
final DataGridController _dataGridController = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextButton(
child: Text('Clear Selection'),
onPressed: () {
_dataGridController.selectedRows = [];
}),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _dataGridController,
selectionMode: SelectionMode.multiple))
]));
}
NOTE
Selected rows and selections will be cleared whenever the
dataSource
is changed at runtime.
Keyboard behavior
Key or KeyCombinations | Description |
---|---|
DownArrow | Moves CurrentCell directly under the active current cell. If the CurrentCell is in the last row, pressing DownArrow does nothing. |
UpArrow | Moves the CurrentCell directly above the active current cell. If the CurrentCell is in the first row, pressing UpArrow does nothing. |
LeftArrow | Moves the current cell to the previous to the active current cell. If the CurrentCell is in the first cell, pressing LeftArrow does nothing. If the focused row is a group header, the group will be collapsed when it is in an expanded state. |
RightArrow | Moves the current cell to next to the active current cell. If the CurrentCell is in the last cell, pressing RightArrow does nothing. If the focused row is a group header, the group will expand when it is in a collapsed state. |
Home / Ctrl + LeftArrow | Moves the current cell to the first cell of the current row. |
End / Ctrl + RightArrow | Moves the current cell to the last cell of the current row. |
PageDown | The SfDataGrid will be scrolled to the next set of rows that are not displayed in the view, including the row that is partially displayed and the current cell is set to the last row. |
PageUp | The SfDataGrid will be scrolled to the previous set of rows that are not displayed in the view, including the row that is partially displayed and the current cell is set to the first row. |
Tab | Moves the current cell to next to the active current cell. If the active current cell is the last cell of the current row, the focus will move to the first cell of the row next to the current row. If the active current cell is the last cell of the last row, the focus will be moved to the next widget in the tab order of the parent container. |
Shift + Tab | Moves the current cell to the previous to the active current cell. If the active current cell is the first cell of the current row, the current cell will move to the last cell of the row previous to the current row. If the active current cell is the first cell of the first row, the focus will be moved to the previous widget in the tab order of the parent container. |
Ctrl + DownArrow | Moves the current cell to the current column of the last row. |
Ctrl + UpArrow | Moves the current cell to the current column of the first row. |
Ctrl + Home | Moves the current cell to the first cell of the first row. |
Ctrl + End | Moves the current cell to the last cell of the last row. |
Enter | The current cell will be moved to the next focused row of the same column. |
Ctrl + A | All rows or cells will be selected. |
F2 | If the DataGrid.AllowEditing property is true and the GridColumn.AllowEditing property is true for the current column, the current cell enters into edit mode. |
Esc | If the current cell is in edit mode, call the DataGridSource.onCellCancelEdit method to revert the current changes and ends the editing. |
Callbacks
The Datagrid provides the following callbacks for selection:
-
onSelectionChanging
: This callback is raised while selecting a row at the execution time before the row is selected. So, it allows canceling the selection action by returningfalse
. -
onSelectionChanged
: This callback is raised after the row is selected.
The followings are the parameters of the onSelectionChanging and onSelectionChanged callbacks,
- newItems: Gets a collection of the
DataGridRow
added for the selection. - oldItems: Gets a collection of the
DataGridRow
removed from the selection.
The following example shows how to cancel the selection when selecting a row that contains the designation of the Manager.
late EmployeeDataSource _employeeDataSource;
List<Employee> _employees = <Employee>[];
@override
void initState() {
super.initState();
_employees = getEmployeeData();
_employeeDataSource = EmployeeDataSource(employees: _employees);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.single,
onSelectionChanging:
(List<DataGridRow> addedRows, List<DataGridRow> removedRows) {
final index = _employeeDataSource.dataGridRows.indexOf(addedRows.last);
Employee employee = _employees[index];
if (employee.designation == 'Manager') {
return false;
}
return true;
},
onSelectionChanged:
(List<DataGridRow> addedRows, List<DataGridRow> removedRows) {
// apply your logic
},
));
}
-
onCurrentCellActivating
: This callback is raised before the current cell applies to the corresponding grid cell of the selecting row. So, it allows canceling the selection action by returningfalse.
If the return is false, the selection will not apply, and also,onSelectionChanging
,onSelectionChanged
andonCurrentCellActivated
are not called. -
onCurrentCellActivated
: This callback is raised after the current cell is applied in the grid cell on the selecting row.
The followings are the parameters of the onCurrentCellActivating and onCurrentCellActivated callbacks,
- newRowColumnIndex: Gets the current RowColumnIndex of the current cell.
- oldRowColumnIndex: Gets the previous RowColumnIndex of the current cell.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.cell,
onCurrentCellActivating: (RowColumnIndex currentRowColumnIndex,
RowColumnIndex previousRowColumnIndex) {
if (currentRowColumnIndex.rowIndex == 2 &&
currentRowColumnIndex.columnIndex == 3) {
return false;
}
return true;
},
onCurrentCellActivated: (RowColumnIndex currentRowColumnIndex,
RowColumnIndex previousRowColumnIndex) {
// apply your logic
},
));
}
Cell Tap callbacks
The Datagrid provides the following callbacks to handle interactions with the cells.
- onCellTap : Called when a tap with a cell has occurred.
- onCellDoubleTap : Called when user is tapped a cell with a primary button at the same cell twice in quick succession.
- onCellLongPress : Called when a long press gesture with a primary button has been recognized for a cell.
- onCellSecondaryTap : Called when a tap with a cell has occurred with a secondary button.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
onCellTap: (DataGridCellTapDetails details) {
print(details);
},
onCellDoubleTap: (DataGridCellDoubleTapDetails details) {
print(details);
},
onCellLongPress: (DataGridCellLongPressDetails details) {
print(details);
},
onCellSecondaryTap: (DataGridCellTapDetails details) {
print(details);
}));
}
Customizing selection behavior
To perform custom actions apart from the functionalities mentioned in the above tables for key press actions of the keyboard, implement your custom actions in the handleKeyEvent() override of the custom written selection manager class derived from RowSelectionManager and assign it to the SfDataGrid.selectionManager property.
final CustomSelectionManager _customSelectionManager = CustomSelectionManager();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple,
selectionManager: _customSelectionManager,
));
}
class CustomSelectionManager extends RowSelectionManager {
@override
void handleKeyEvent(KeyEvent keyEvent) {
if (keyEvent.logicalKey == LogicalKeyboardKey.keyA) {
if (HardwareKeyboard.instance.isControlPressed) {
//apply your logic
return;
}
}
super.handleKeyEvent(keyEvent);
}
}
Change Enter key behavior
When pressing the Enter key, the current cell will be moved to the next focused row of the same column, by default. The following code shows how to change the Enter key behavior by overriding the handleKeyEvent()
method in RowSelectionManager
.
final CustomSelectionManager _customSelectionManager = CustomSelectionManager();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple,
navigationMode: GridNavigationMode.cell,
selectionManager: _customSelectionManager,
)));
}
class CustomSelectionManager extends RowSelectionManager {
@override
void handleKeyEvent(KeyEvent keyEvent) {
if (keyEvent.logicalKey == LogicalKeyboardKey.enter) {
//apply your logic
return;
}
super.handleKeyEvent(keyEvent);
}
}
Appearance
The SfDataGrid allows customizing the appearance of the selected rows and current cell through the SfDataGridTheme.SfDataGridThemeData property.
All the styles such as selectionColor, and DataGridCurrentCellStyle related to SfDataGrid
are available in the syncfusion_flutter_core package. To access those classes, import the following file in your application.
import 'package:syncfusion_flutter_core/theme.dart';
Selection
The selection background can be changed by the selectionColor
property of the SfDataGridThemeData
in SfDataGridTheme.
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
final DataGridController _dataGridController = DataGridController();
late EmployeeDataSource _employeeDataSource;
@override
void initState() {
super.initState();
_employeeDataSource = EmployeeDataSource(_dataGridController);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(selectionColor: Colors.red),
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple,
)));
}
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource(this.dataGridController) {
dataGridRows = _employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
final DataGridController dataGridController;
List<DataGridRow> dataGridRows = [];
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
TextStyle? getSelectionTextStyle() {
return dataGridController.selectedRows.contains(row)
? TextStyle(
fontFamily: 'Raleway',
fontWeight: FontWeight.w300,
color: Colors.white,
)
: null;
}
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
color: Colors.transparent,
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: getSelectionTextStyle(),
),
);
}).toList());
}
}
Current cell
The current cell border’s color and thickness can be changed by the currentCellStyle property of SfDataGridThemeData
in SfDataGridTheme.
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
currentCellStyle: DataGridCurrentCellStyle(
borderWidth: 2, borderColor: Colors.pinkAccent)),
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple,
navigationMode: GridNavigationMode.cell,
)));
}
NOTE
You can change the current row border’s color by thecurrentCellStyle
property ofSfDataGridThemeData
inSfDataGridTheme
. The current row border is shown when navigationMode is row to navigate between rows.