Grouping in Flutter DataGrid (SfDataGrid)

19 Dec 202324 minutes to read

Grouping in a DataGrid involves organizing and categorizing data based on specific criteria or field values. This feature enables the grouping of related records together, forming a hierarchical structure within the SfDataGrid. Each group is represented by the CaptionSummaryRow that displays at the top of each group and holds the caption summary value of that group.

By default, the DataGrid doesn’t show the group’s caption summary value. To showcase the caption summary value, it is necessary to override the DataGridSource.buildGroupCaptionCellWidget method. This method receives the caption summary value as a parameter. Consequently, you will be required to return the necessary widget containing the summary value.

Programmatic grouping

Add column group

To enable column grouping, add the ColumnGroup instance through the `DataGridSource.addColumnGroup method.

The ColumnGroup object consists of the following properties:

  • name: The column name of the GridColumn to be grouped.
  • sortGroupRows: Determines whether to group the column with ascending sorting or not.

The following code demonstrates how to apply grouping to a column

class SfDataGridDemoState extends State<SfDataGridDemo> {
  List<Employee> employees = <Employee>[];
  late EmployeeDataSource employeeDataSource;

  @override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text(
                      'ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource({required List<Employee> employeeData}) {
    dataGridRows = employeeData
        .map<DataGridRow>((e) => DataGridRow(cells: [
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<double>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  List<DataGridRow> dataGridRows = [];

  @override
  List<DataGridRow> get rows => dataGridRows;

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((e) {
      return Container(
        alignment: Alignment.center,
        padding: EdgeInsets.all(8),
        child: Text(
          e.value.toString(),
        ),
      );
    }).toList());
  }

  @override
  Widget? buildGroupCaptionCellWidget(
      RowColumnIndex rowColumnIndex, String summaryValue) {
    return Container(
        padding: EdgeInsets.symmetric(horizontal: 12, vertical: 15),
        child: Text(summaryValue));
  }
}

Flutter datagrid shows the single level grouping

Remove column group

To disable column grouping for a particular column, remove that ColumnGroup instance using the DataGridSource.removeColumnGroup` method.

@override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true));
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: false));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: Column(children: [
        ElevatedButton(
            onPressed: () {
              setState(() {});
              ColumnGroup? group = employeeDataSource.groupedColumns
                  .firstWhereOrNull((element) => element.name == 'Salary');
              if (group != null) {
                employeeDataSource.removeColumnGroup(group);
              }
            },
            child: Text('Remove Salary Column Group')),
        Expanded(
            child: SfDataGrid(
                source: employeeDataSource,
                allowExpandCollapseGroup: true,
                columns: <GridColumn>[
              GridColumn(
                  columnName: 'ID',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('ID'))),
              GridColumn(
                  columnName: 'Name',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Name'))),
              GridColumn(
                  columnName: 'Designation',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Designation',
                          overflow: TextOverflow.ellipsis))),
              GridColumn(
                  columnName: 'Salary',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Salary'))),
            ])),
      ]),
    );
  }

Clear all column groups

To clear all the column groups, simply call the DataGridSource.clearColumnGroups method.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: Column(children: [
        ElevatedButton(
            onPressed: () {
              setState(() {});
              employeeDataSource.clearColumnGroups();
            },
            child: Text('Clear all column groups')),
        Expanded(
            child: SfDataGrid(
                source: employeeDataSource,
                allowExpandCollapseGroup: true,
                columns: <GridColumn>[
              GridColumn(
                  columnName: 'ID',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('ID'))),
              GridColumn(
                  columnName: 'Name',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Name'))),
              GridColumn(
                  columnName: 'Designation',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Designation',
                          overflow: TextOverflow.ellipsis))),
              GridColumn(
                  columnName: 'Salary',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Salary'))),
            ])),
      ]),
    );
  }

Multi-level grouping

The SfDataGrid allows grouping of data against one or more columns by adding multiple columns to the DataGridSource.addColumnGroup property. This feature organizes data into a hierarchical tree structure based on identical values within those columns.

Initially, data is grouped according to the first column added to the DataGridSource.addColumnGroup property. Subsequently, when additional columns are included in DataGridSource.addColumnGroup, each new column is grouped in consideration of the existing group(s). This process creates a tree-like hierarchy. To enable multi-grouping, please refer to the following code snippet:

@override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true));
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: false));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text(
                      'ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

Flutter datagrid shows the multi level grouping

Callbacks

The SfDataGrid provides the following callbacks to notify the grouping stages:

GroupExpanding

The SfDataGrid.groupExpanding callback is invoked when the group is being expanded. You can return false from this callback to restrict the group from being expanded.

@override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupExpanding: (group) {
            print('Group expanding: ${group.key}');
            print('Group level: ${group.groupLevel}');
            return true;
          },
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

GroupExpanded

The SfDataGrid.groupExpanded callback is invoked when the group is expanded.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupExpanded: (group) {
            print('Group expanding: ${group.key}');
            print('Group level: ${group.groupLevel}');
          },
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

GroupCollapsing

The SfDataGrid.groupCollapsing callback is invoked when the group is being collapsed. You can return false from this callback to restrict the group from being collapsed.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupCollapsing: (group) {
            print('Group expanding: ${group.key}');
            print('Group level: ${group.groupLevel}');
            return true;
          },
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

GroupCollapsed

The SfDataGrid.groupCollapsed callback is invoked when the group is collapsed.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupCollapsed: (group) {
            print('Group expanding: ${group.key}');
            print('Group level: ${group.groupLevel}');
          },
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

Custom grouping

The SfDataGrid provides support to group a column using custom logic when standard grouping techniques aren’t sufficient for specific requirements. This can be accomplished by overriding the DataGridSource.performGrouping method.

The DataGridSource.performGrouping method is invoked when grouping is applied to the SfDataGrid. Within this method, you can implement custom logic to return a String based on your specific requirements.

@override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: true));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupExpanded: (group) {
            print('Group expanding: ${group.key}');
            print('Group level: ${group.groupLevel}');
          },
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource({required List<Employee> employeeData}) {
    dataGridRows = employeeData
        .map<DataGridRow>((e) => DataGridRow(cells: [
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<double>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  List<DataGridRow> dataGridRows = [];

  @override
  List<DataGridRow> get rows => dataGridRows;

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((e) {
      return Container(
        alignment: Alignment.center,
        padding: EdgeInsets.all(8),
        child: Text(
          e.value.toString(),
        ),
      );
    }).toList());
  }

  @override
  Widget? buildGroupCaptionCellWidget(
      RowColumnIndex rowColumnIndex, String summaryValue) {
    return Container(
        padding: EdgeInsets.symmetric(horizontal: 12, vertical: 15),
        child: Text(summaryValue));
  }

  @override
  String performGrouping(String columnName, DataGridRow row) {
    if (columnName == 'Salary') {
      final double total = row
          .getCells()
          .firstWhereOrNull(
              (DataGridCell cell) => cell.columnName == columnName)!
          .value;
      if (total > 100000 && total <= 200000) {
        return '> 100 K & <= 150 K';
      } else if (total > 90000 && total <= 100000) {
        return '> 90 K & <= 100 K';
      } else if (total > 50000 && total <= 90000) {
        return '> 50 K & <= 90 K';
      } else if (total > 30000 && total <= 50000) {
        return '> 30 K & <= 50 K';
      } else {
        return '<= 30 K';
      }
    }
    return super.performGrouping(columnName, row);
  }
}

Flutter datagrid shows the custom grouping

Enable group expand and collapse

The group expand and collapse functionality can be enabled by setting the SfDataGrid.allowExpandCollapseGroup property to true. The default value of this property is false.

@override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
    employeeDataSource
        .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: true));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

Disable group expanding on the initial loading

By default, the SfDataGrid always expands all the groups. All the groups can be collapsed intially by setting the SfDataGrid.autoExpandGroups property to false.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          autoExpandGroups: false,
          allowExpandCollapseGroup: true,
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

Programmatically expand and collapse groups

Expanding and collapsing groups programmatically can be achieved using the following DataGridController methods,

Method Description
DataGridController.expandAllGroup Expands all the groups in the SfDataGrid
DataGridController.collapseAllGroup. Collapses all the groups in the SfDataGrid
DataGridController.expandGroupsAtLevel. Expands the group based on the group level
DataGridController.collapseGroupsAtLevel. Collapses the group based on the group level

Customize the group caption summary row format

The caption summary value is displayed in a caption summary row by the default format '{ColumnName} : {Key} - {ItemsCount} Items'. The {ColumnName} defines the name of the grouped column, {Key} defines the identical cell value of the group, and {ItemsCount} defines the length of the rows in the group.

The format can be customized by using the SfDataGrid.groupCaptionTitleFormat property.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGrid(
          source: employeeDataSource,
          allowExpandCollapseGroup: true,
          groupCaptionTitleFormat: '{ColumnName} : {Key} - {ItemsCount}',
          columns: <GridColumn>[
            GridColumn(
                columnName: 'ID',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('ID'))),
            GridColumn(
                columnName: 'Name',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Name'))),
            GridColumn(
                columnName: 'Designation',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child:
                        Text('Designation', overflow: TextOverflow.ellipsis))),
            GridColumn(
                columnName: 'Salary',
                label: Container(
                    padding: EdgeInsets.all(8),
                    alignment: Alignment.center,
                    child: Text('Salary'))),
          ]),
    );
  }

Flutter datagrid shows the customized summary format

Customize the indent column appearance

The width and color of the indent column can be personalized using the SfDataGridThemeData.indentColumnWidth and SfDataGridThemeData.indentColumnColor properties. The default values for these properties are 40.0 and null, respectively.

import 'package:syncfusion_flutter_core/theme.dart';
 import 'package:syncfusion_flutter_datagrid/datagrid.dart';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGridTheme(
        data: SfDataGridThemeData(
            indentColumnWidth: 100, indentColumnColor: Colors.amber),
        child: SfDataGrid(
            source: employeeDataSource,
            allowExpandCollapseGroup: true,
            columns: <GridColumn>[
              GridColumn(
                  columnName: 'ID',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('ID'))),
              GridColumn(
                  columnName: 'Name',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Name'))),
              GridColumn(
                  columnName: 'Designation',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Designation',
                          overflow: TextOverflow.ellipsis))),
              GridColumn(
                  columnName: 'Salary',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Salary'))),
            ]),
      ),
    );
  }

Customize the group expander icon

The group expander icon is used to indicate the state of a group. It is displayed only when the SfDataGrid.allowExpandCollapseGroup option is enabled. The icon can be customized by using the SfDataGridThemeData.groupExpanderIcon property.

The SfDataGridThemeData and SfDataGridTheme classes are available in the syncfusion_flutter_core package.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: SfDataGridTheme(
        data: SfDataGridThemeData(
            groupExpanderIcon: Icon(Icons.expand_circle_down_outlined,
                size: 20, color: Colors.pink)),
        child: SfDataGrid(
            source: employeeDataSource,
            allowExpandCollapseGroup: true,
            columns: <GridColumn>[
              GridColumn(
                  columnName: 'ID',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('ID'))),
              GridColumn(
                  columnName: 'Name',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Name'))),
              GridColumn(
                  columnName: 'Designation',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Designation',
                          overflow: TextOverflow.ellipsis))),
              GridColumn(
                  columnName: 'Salary',
                  label: Container(
                      padding: EdgeInsets.all(8),
                      alignment: Alignment.center,
                      child: Text('Salary'))),
            ]),
      ),
    );
  }

Flutter datagrid shows the custom group expander icon

Limitations

  • The grouping will be refreshed when performing CRUD operations on the DataGridSource.rows and the SfDataGrid.columns.` Consequently, this action resets the expand and collapse states of the groups based on the SfDataGrid.autoExpandGroups property.
  • To prevent unnecessary grouping refresh, ensure that the SfDataGrid.columns property is set as an instance.