Selection in Flutter DataGrid (SfDataGrid)

24 Sep 202124 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 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 source. rows is the collection of DataGridRow 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,
    ),
  );
}

flutter datagrid shows currentCell

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));
}

flutter datagrid shows single row selection

Multiple row selection

The SfDataGrid allows you to select multiple rows by setting 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));
}

flutter datagrid shows multiple row selection

NOTE

When the selectionMode is multiple, multiple rows can be selected or deselected by clicking the respective rows. In multiple selection, pressing 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

You can get the information of selected rows by using controller property. Create an instance of DataGridController and set to controller property. The selectedRow property returns the selected DataGridRow and the selectedIndex property returns the index of the selectedRow in SfDataGrid. selectedRow denotes the last selected row in multiple selection.

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 a value other than none, selected row/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 collection of DataGridRow to 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))
  ]));
}

flutter datagrid shows multiple row selection

Get the current cell

The current cell information such as row index, 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 selectionMode property is in single or singleDeselect. On selectionMode property is in multiple you can clear the selection from grid rows by setting the DataGridController.selectedRows to empty.

The following code example shows how to clear selection when 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 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 below the active current cell. If the CurrentCell is in last row, pressing DownArrow does nothing.
UpArrow Moves the CurrentCell directly above the active current cell. If the CurrentCell is in first row, pressing UpArrow does nothing.
LeftArrow Moves the current cell to previous to the active current cell. If the CurrentCell is in first cell, pressing LeftArrow does nothing. If the focused row is group header, the group will be collapsed when it is in expanded state.
RightArrow Moves the current cell to next to the active current cell. If the CurrentCell is in last cell, pressing RightArrow does nothing. If the focused row is group header, the group will expanded when it is in 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 next set of rows that are not displayed in view, including the row that are partially displayed and the current cell is set to last row.
PageUp The SfDataGrid will be scrolled to previous set of rows that are not displayed in view, including the row that are 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 moved to 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 next widget in the tab order of the parent container.
Shift + Tab Moves the current cell to previous to the active current cell. If the active current cell is the first cell of the current row, the current cell will moved to 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 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](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowEditing.html) property is true and the [GridColumn.AllowEditing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/allowEditing.html) property is true for the current column, the current cell enters into edit mode.
Esc If the current cell is in edit mode, calls the [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) 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 return false.
  • onSelectionChanged : This callback is raised after the row is selected.

The followings are the parameters of the onSelectionChanging and onSelectionChanged callbacks,

  • newItems: Gets collection of the DataGridRow added for selection.
  • oldItems: Gets collection of the DataGridRow removed from selection.

The following example shows how to cancel the selection when select a row which contains the designation as 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 logics
    },
  ));
}
  • onCurrentCellActivating: This callback is raised before the current cell applying to the corresponding grid cell of the selecting row. So it allows canceling the selection action by return false. If return false, the selection will not apply and also onSelectionChanging, onSelectionChanged and onCurrentCellActivated are not called.
  • onCurrentCellActivated: This callback is raised after the current cell applied in grid cell on the selecting row.

The followings are the parameters of the onCurrentCellActivating and onCurrentCellActivated callbacks,

  • newRowColumnIndex: Gets current RowColumnIndex of the current cell.
  • oldRowColumnIndex: Gets 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 logics
    },
  ));
}

Cell Tap callbacks

The datagrid provides the following callbacks to handle interactions to 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(RawKeyEvent keyEvent) {
    if (keyEvent.logicalKey == LogicalKeyboardKey.keyA) {
      if (keyEvent.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(RawKeyEvent keyEvent) {
    if (keyEvent.logicalKey == LogicalKeyboardKey.enter) {
      //apply your logic
      return;
    }

    super.handleKeyEvent(keyEvent);
  }
}

Appearance

SfDataGrid allows to customize the appearance of the selected rows and current cell through SfDataGridTheme.SfDataGridThemeData property.

All the style such as selectionColor, DataGridCurrentCellStyle related to SfDataGrid are available in the syncfusion_flutter_core package. To access those classes, import the below file in your application,

import 'package:syncfusion_flutter_core/theme.dart';

Selection

The selection background can be changed by selectionColor property of 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());
  }
}

flutter datagrid shows customized multiple selection

Current cell

The current cell border’s color and thickness can be changed by 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,
          )));
}

flutter datagrid shows customized current cell