Grid Group By

A Group by behavior in an Angular Material table or UI grid creates grouped data rows based on the column values. The Group By in igxGrid allows for visualizing the groups in a hierarchical structure. The grouped data rows can be expanded or collapsed and the order of grouping may be changed through the UI or API.

Demo

Initial Grouping State

It is possible to define initial grouping of the grid by assigning an array of expressions to the groupingExpressions property of the grid.

public ngOnInit() {
    grid.groupingExpressions = [
        { fieldName: 'ProductName', dir: SortingDirection.Desc },
        { fieldName: 'Released', dir: SortingDirection.Desc }
    ];
}

Grouping expressions implement the ISortingExpression interface.

Group By API

Grouping is available through the UI and through a robust API exposed by the grid component. Developers can allow end-users to group the grid data by certain columns, by setting each column's groupable property to true.

<igx-grid [data]="data">
    <igx-column *ngFor="let c of columns" [field]="c.field" [groupable]="true">
    </igx-column>
</igx-grid>
public ngOnInit() {
    grid.columns.forEach((column) => {
        column.groupable = true;
    });
}

During runtime the expressions are gettable and settable from the groupingExpressions property. If you need to add or change an existing expression you may also use the groupBy method with either a single or an array of ISortingExpression.

grid.groupBy({ fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: true });

Grouping works in conjunction with sorting and grouping expressions are applied as sorting ones even though columns may be sorted without being grouped. You will always find the grouping expressions in the sortingExpressions property, sorted in a way that grouped columns' expressions are always first. The sorting API will affect grouping if it changes the expression for a column that is grouped. Removing a grouping expression (ungrouping a column) also unsorts it.

In addition to grouping expressions you can also control the expansion states for group rows. They are stored in a separate property of the igxGrid component groupingExpansionState. A group row is uniquely identified based on the field name it is created for and the value it represents for each level of grouping. This means that the signature of an expansion state interface is the following:

export interface IGroupByKey {
    fieldName: string;
    value: any;
}

export interface IGroupByExpandState {
    hierarchy: Array<IGroupByKey>;
    expanded: boolean;
}

As with groupingExpressions, setting a list of IGroupByExpandState directly to the groupingExpansionState will change the expansion accordingly. Additionally igxGrid exposes a method that toggles a group by the group record instance.

    const groupRow = this.grid.groupsRecords.find(r => r.value === "France");
    grid.toggleGroup(groupRow);

Groups can be created expanded (default) or collapsed and the expansion states would generally only contain the state opposite to the default behavior. You can control whether groups should be created expanded or not through the groupsExpanded property.

Group Row Templates

The group row without its expand/collapse UI is fully templatable. By default it renders a grouping icon and displays the field name and value it represents. The grouping record template is rendered against has the following signature:

export interface IGroupByRecord {
    expression: ISortingExpression;
    level: number;
    records: GroupedRecords;
    value: any;
    groupParent: IGroupByRecord;
    groups?: IGroupByRecord[];
}

As an example, the following template would make the group rows summary more verbose:

<ng-template igxGroupByRow let-groupRow>
    <span>Total items with value: {{ groupRow.value }} are {{ groupRow.records.length }}</span>
</ng-template>

Group By with Paging

Group rows participate in the paging process along with data rows. They count towards the page size for each page. Collapsed rows are not included in the paging process. Any expand or collapse operation forces Paging to recalculate the page count and adjust the page index if necessary. Groups that span multiple pages are split between them. The group row is visible only on the page it starts on and is not repeated on subsequent pages. Summary information for group rows is calculated based on the whole group and is unaffected by Paging.

Demo

Group By with Summaries

Integration between Group By and Summaries is described in the Summaries topic.

Keyboard Navigation

The grouping UI supports the following keyboard interactions:

  • For group rows (focus should be on the row or the expand/collapse cell)

    • ALT + RIGHT - Expands the group
    • ALT + LEFT - Collapses the group
  • For group igxChip components in the group by area (focus should be on the chip)

    • SHIFT + LEFT - moves the focused chip left, changing the grouping order, if possible
    • SHIFT + RIGHT - moves the focused chip right, changing the grouping order, if possible
    • SPACE - changes the sorting direction
    • DELETE - ungroups the field
    • The seperate elements of the chip are also focusable and can be interacted with using the ENTER key.

Styling

The igxGrid allows styling through the Ignite UI for Angular Theme Library. The grid's theme exposes a wide variety of properties, which allow the customization of all the features of the grid.

In the below steps, we are going through the steps of customizing the grid's Group By styling.

Importing global theme

To begin the customization of the Group By feature, you need to import the index file, where all styling functions and mixins are located.

@import '~igniteui-angular/lib/core/styles/themes/index'

Defining custom theme

Next, create a new theme, that extends the igx-grid-theme and accepts the parameters, required to customize the Group By as desired. You also need to extend the igx-chip-theme, because it's used in the Group By feature.


$custom-theme: igx-grid-theme(
    /* Group By properties that affect styling */
    $group-row-background: #494949,
    $group-row-selected-background: #383838,
    $group-label-column-name-text: #f8f8f8,
    $group-label-icon: #FFCD0F,
    $group-label-text: #f8f8f8,
    $group-count-background: #FFCD0F,
    $group-count-text-color: #000,
    $expand-icon-color: #FFCD0F,
    $expand-icon-hover-color: rgb(223, 181, 13),
    $cell-active-border-color: #FFCD0F,
    $row-selected-background: #fff6d3,
    $row-selected-text-color: #000,
    $drop-indicator-color: #FFCD0F
    /* add other features properties here... */
);

/* Chip theme will style the chips in the Group By area */
$custom-chips-theme: igx-chip-theme(
    $background: #494949,
    $text-color: #f8f8f8,
    $hover-text-color: #e7e7e7
);

Defining a custom color palette

In the approach that we described above, the color values were hardcoded. Alternatively, you can achieve greater flexibility, using the igx-palette and igx-color functions.
igx-palette generates a color palette, based on provided primary and secondary colors.

$black-color: #292826;
$yellow-color: #FFCD0F;

$custom-palette: igx-palette(
  $primary: $black-color,
  $secondary: $yellow-color
);

After a custom palette has been generated, the igx-color function can be used to obtain different varieties of the primary and the secondary colors.

$custom-theme: igx-grid-theme(
    $group-row-background: igx-color($custom-palette, "primary", 300),
    $group-row-selected-background: igx-color($custom-palette, "primary", 400),
    $group-label-column-name-text: igx-contrast-color($custom-palette, "primary", 500),
    $group-label-icon: igx-color($custom-palette, "secondary", 600),
    $group-label-text: igx-contrast-color($custom-palette, "primary", 500),
    $group-count-background: igx-color($custom-palette, "secondary", 600),
    $group-count-text-color: igx-color($custom-palette, "primary", 400),
    $expand-icon-color: igx-color($custom-palette, "secondary", 600),
    $expand-icon-hover-color: igx-color($custom-palette, "secondary", 300),
    $cell-active-border-color: igx-color($custom-palette, "secondary", 600)
);

$custom-chips-theme: igx-chip-theme(
    $background: igx-color($custom-palette, "primary", 300),
    $text-color: igx-contrast-color($custom-palette, "primary", 500),
    $hover-text-color: igx-contrast-color($custom-palette, "primary", 600)
);

Defining custom schemas

You can go even further and build flexible structure that has all the benefits of a schema. The schema is the recipe of a theme. Extend one of the two predefined schemas, that are provided for every component. In our case, we would use $_light_grid.

$custom-grid-schema: extend($_light-grid,(
    group-row-background: (igx-color:('secondary', 100)),
    group-row-selected-background: (igx-color:('primary', 400)),
    group-label-column-name-text: (igx-color:('primary', 600)),
    group-label-icon: (igx-color:('primary', 600)),
    group-label-text: (igx-color:('secondary', 700)),
    group-count-background: (igx-color:('primary', 600)),
    group-count-text-color: (igx-color:('secondary', 400)),
    expand-icon-color: (igx-color:('primary', 600)),
    expand-icon-hover-color: (igx-color:('primary', 400))
));

In order for the custom schema to be applied, either light, or dark globals has to be extended. The whole process is actually supplying a component with a custom schema and adding it to the respective component theme afterwards.

$my-custom-schema: extend($light-schema, ( 
    igx-grid: $custom-grid-schema
));

$custom-theme: igx-grid-theme(
    $palette: $custom-palette,
    $schema: $my-custom-schema
);

Applying the custom theme

The easiest way to apply your theme is with a sass @include statement in the global styles file:

@include igx-grid($custom-theme);
@include igx-chip($custom-chips-theme);

Scoped component theme

In order for the custom theme to affect only specific component, you can move all of the styles you just defined from the global styles file to the custom component's style file (including the import of the index file).

This way, due to Angular's ViewEncapsulation, your styles will be applied only to your custom component.

Note

If the component is using an Emulated ViewEncapsulation, it is necessary to penetrate this encapsulation using ::ng-deep in order to style the grid.

Note

Wrap the statement inside of a :host selector to prevent your styles from affecting elements outside of our component:

:host {
    ::ng-deep {
        @include igx-grid($custom-theme);
        @include igx-chip($custom-chips-theme);
    }
}

Demo

Known Limitations

Limitation Description
Maximum amount of grouped columns is 10. If more than 10 columns are grouped an error is thrown.

API References

Additional Resources

Our community is active and always welcoming to new ideas.