Row grouping

Row grouping

·

5 min read

Row grouping is a function to group rows of PlutoGrid.

Group by column

Rows are grouped by grouping cell values ​​based on a specified column.
PlutoRows are automatically grouped by cell value without the user having to group them.

// In the onLoaded callback of PlutoGrid, set the delegate as shown below.
onLoaded: (e) => e.stateManager.setRowGroup(PlutoRowGroupByColumnDelegate(
  columns: [
    e.stateManager.columns[0],
    e.stateManager.columns[1],
  ],
  // Decide whether to display the expand/collapse buttons in the first cell.
  // To set this value to true when grouped by column,
  // You need to hide the columns except for the first column.
  // stateManager.hideColumns(stateManager.columns[1]);
  // If this value is false, expand/collapse buttons are displayed to fit the column depth.
  showFirstExpandableIcon: false,
  // Decide whether to display the number of sub-rows of the grouped column in the cell.
  showCount: true,
  // Decide whether to display a summary when displaying the number of sub-rows.
  // ex) 1,234,567 > 1.2M
  enableCompactCount: true,
)),

Tree structure grouping

Rows are grouped by user-defined criteria.
User needs to group PlutoRows and pass them to PlutoGrid.

// Set the type of PlutoRow to group as shown below,
// Grouping rows should be delivered to rows of PlutoGrid.
// The type of every row does not have to be group.
PlutoRow(
  cells: {'files': PlutoCell(value: 'PlutoGrid')},
  type: PlutoRowType.group(
      children: FilteredList<PlutoRow>(
    initialList: [
      PlutoRow(
        cells: {'files': PlutoCell(value: 'lib')},
        type: PlutoRowType.group(
          children: FilteredList<PlutoRow>(
            initialList: [
              PlutoRow(
                cells: {'files': PlutoCell(value: 'src')},
                type: PlutoRowType.group(
                    children: FilteredList<PlutoRow>(
                  initialList: [
                    PlutoRow(cells: {
                      'files': PlutoCell(value: 'pluto_grid.dart')
                    }),
                    PlutoRow(cells: {
                      'files': PlutoCell(value: 'pluto_dual_grid.dart')
                    }),
                  ],
                )),
              ),
            ],
          ),
        ),
      ),
      PlutoRow(
        cells: {'files': PlutoCell(value: 'test')},
        type: PlutoRowType.group(
          children: FilteredList<PlutoRow>(
            initialList: [
              PlutoRow(
                cells: {
                  'files': PlutoCell(value: 'pluto_grid_test.dart')
                },
              ),
            ],
          ),
        ),
      ),
    ],
  )),
),
PlutoRow(
  cells: {'files': PlutoCell(value: 'PlutoMenuBar')},
  type: PlutoRowType.group(
      children: FilteredList<PlutoRow>(
    initialList: [
      PlutoRow(
        cells: {'files': PlutoCell(value: 'pluto_menu_bar.dart')},
      ),
    ],
  )),
),

// In the onLoaded callback of PlutoGrid, set the delegate as shown below.
onLoaded: (e) => e.stateManager.setRowGroup(PlutoRowGroupTreeDelegate(
  // Determine the depth of the column.
  // Basically, the order in which the columns are displayed on the screen is the column depth.
  // Pass the settings below as default.
  resolveColumnDepth: (column) => e.stateManager.columnIndex(column),
  // Determines whether the cell's text is visible.
  // If true is returned, the text of all cells is shown.
  // If you want to hide the text of a specific cell,  
  // you can define the return value of the cell with a specific condition as false.
  showText: (cell) => true,
  // Decide whether to display the expand/collapse buttons in the first cell.
  // If this value is false, expand/collapse buttons are displayed to fit the column depth.
  showFirstExpandableIcon: true,
  // Decide whether to display the number of sub-rows of the grouped column in the cell.
  showCount: true,
  // Decide whether to display a summary when displaying the number of sub-rows.
  // ex) 1,234,567 > 1.2M
  enableCompactCount: true,
)),

Groupby columns dynamically

The example below dynamically processes group-by columns by adding the to Group, unGroup buttons to the right menu of the column.

PlutoGrid(
  columns: columns,
  rows: rows,
  onLoaded: (PlutoGridOnLoadedEvent event) {
    stateManager = event.stateManager;
    stateManager.setRowGroup(
      // First, the columns of the PlutoRowGroupByColumnDelegate 
      // start with an empty list.
      PlutoRowGroupByColumnDelegate(
        columns: [],
      ),
    );
  },
  // Set a custom column menu delegate to add a button to the column menu.
  columnMenuDelegate: _CustomColumnMenuDelegate(),
),

class _CustomColumnMenuDelegate implements PlutoColumnMenuDelegate {
  final PlutoColumnMenuDelegateDefault defaultDelegate =
      const PlutoColumnMenuDelegateDefault();

  bool isGroupColumn(PlutoGridStateManager stateManager, PlutoColumn column) {
    return (stateManager.rowGroupDelegate as PlutoRowGroupByColumnDelegate)
        .columns
        .contains(column);
  }

  @override
  List<PopupMenuEntry<dynamic>> buildMenuItems({
    required PlutoGridStateManager stateManager,
    required PlutoColumn column,
  }) {
    final Color textColor = stateManager.style.cellTextStyle.color!;

    final groupColumn = isGroupColumn(stateManager, column);

    return [
      ...defaultDelegate.buildMenuItems(
          stateManager: stateManager, column: column),
      PopupMenuItem<dynamic>(
        value: groupColumn ? _CustomMenuItem.unGroup : _CustomMenuItem.toGroup,
        height: 36,
        enabled: true,
        child: Text(
          groupColumn ? 'unGroup' : 'toGroup',
          style: TextStyle(
            color: textColor,
            fontSize: 13,
          ),
        ),
      ),
    ];
  }

  @override
  void onSelected({
    required BuildContext context,
    required PlutoGridStateManager stateManager,
    required PlutoColumn column,
    required bool mounted,
    required selected,
  }) {
    if (selected is PlutoGridColumnMenuItem) {
      defaultDelegate.onSelected(
        context: context,
        stateManager: stateManager,
        column: column,
        mounted: mounted,
        selected: selected,
      );
    } else if (selected is _CustomMenuItem) {
      switch (selected) {
        case _CustomMenuItem.toGroup:
          stateManager.setRowGroup(PlutoRowGroupByColumnDelegate(columns: [
            ...(stateManager.rowGroupDelegate as PlutoRowGroupByColumnDelegate)
                .columns,
            column,
          ]));
          stateManager.updateVisibilityLayout();
          break;
        case _CustomMenuItem.unGroup:
          stateManager.setRowGroup(PlutoRowGroupByColumnDelegate(columns: [
            ...(stateManager.rowGroupDelegate as PlutoRowGroupByColumnDelegate)
                .columns
                .where((e) => e.field != column.field),
          ]));
          stateManager.updateVisibilityLayout();
          break;
      }
    }
  }
}

enum _CustomMenuItem {
  toGroup,
  unGroup,
}

Bottom aggregate column in grouping state

weblaze.dev/pluto_grid/build/web/#feature/c..
When adding an aggregate column at the bottom of the link above, you can set the groupedRowType property to set the conditions for the rows to be included in the aggregation in the grouping state.

columns[0].footerRenderer = (c) {
  return PlutoAggregateColumnFooter(
    rendererContext: c,
    type: PlutoAggregateColumnType.count,
    // The groupedRowType property takes effect when rows are grouped.
    groupedRowType: PlutoAggregateColumnGroupedRowType.rows,
    format: 'CheckedCount : #,###',
    alignment: Alignment.center,
    filter: (cell) => cell.row.checked == true,
  );
};

// Include all groups and rows in the aggregation.
PlutoAggregateColumnGroupedRowType.all
// Include groups and rows excluding collapsed sub-rows in the aggregation.
PlutoAggregateColumnGroupedRowType.expandedAll
// Include rows excluding group rows in the aggregation.
PlutoAggregateColumnGroupedRowType.rows
// Include expanded rows excluding group rows in the aggregate.
PlutoAggregateColumnGroupedRowType.expandedRows

Restrictions

  • In version 5.2.0, the drag function of the row in the grouping state is not yet supported.
  • If a row is added when grouped by column, if there is a duplicate value according to the cell value of the row being added, it is included in the existing group. Otherwise, a new group is added.

weblaze.dev/pluto_grid/build/web/#feature/r..