# Row Grouping

## Live example

{% hint style="success" %}
[Row Grouping](https://demos.dikesoft.com/dk-grid/row/grouping) live example.
{% endhint %}

## Allowing the Row-Grouping operation

To allow the user to **group** the DkGrid rows, you must provide an input property named <mark style="color:orange;">`allowRowGrouping`</mark>.

{% code title="row-grouping.component.html" %}

```markup
<dike-grid id="grid-row-grouping" height="700px" #grid="dkgGrid"
    allowRowGrouping>
</dike-grid>
```

{% endcode %}

{% hint style="warning" %}
You can set the value of the <mark style="color:orange;">`allowRowGrouping`</mark> property only at creation time.
{% endhint %}

After enabling the row-grouping operation, you will see a panel above the column headers. This panel is the **group panel**.

![Group panel](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FYCQdbtrLfFedbQ8zouYa%2Frow-grouping-group-panel.png?alt=media\&token=3eb2df40-26bd-4c54-b579-3bfb706ffe5a)

## Row Grouping through the UI

To allow the user to move columns to the **group panel**, you must provide an input property named <mark style="color:orange;">`allowColumnDragging`</mark>. Then, mark the columns you want the DkGrid rows grouped by as **draggable** and **groupable**.

{% code title="row-grouping.component.html" %}

```markup
<dk-grid id="grid-row-grouping" height="700px" #grid="dkGrid"
    allowRowGrouping
    [allowColumnDragging]="gridProperties.allowColumnDragging">

    <dk-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dk-grid-column>

    <dk-grid-column
        fieldName="country"
        headerText="Country"
        dataType="Text"
        width="250"
        groupable
        draggable>
    </dk-grid-column>

    <dk-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name">

        <dk-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            groupable
            draggable>
        </dk-grid-column>

        <dk-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            draggable>
        </dk-grid-column>

    </dk-grid-column>

    <dk-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="130"
        draggable
        groupable>
    </dk-grid-column>

    <dk-grid-column
        fieldName="age"
        headerText="Age"
        dataType="Numeric"
        contentAlign="center"
        width="100"
        draggable
        groupable>
    </dk-grid-column>

    <dk-grid-column
        fieldName="email"
        headerText="Email"
        dataType="Text"
        width="300">
    </dk-grid-column>

    <dk-grid-column
        fieldName="hireDate"
        headerText="Hire Date"
        dataType="Date"
        width="150">
    </dk-grid-column>

</dk-grid>
```

{% endcode %}

We have defined **Country**, **Age**, **Gender,** and **Name** columns as **draggable** and **groupable**.

{% hint style="info" %}
Remember, you should not **lock** a column if you want to **drag** that column.
{% endhint %}

Open the [Floating Configuration Panel](https://docs.dikesoft.com/overview#floating-configuration-panel) and mark the **Allow Column Dragging** checkbox.

![Floating Configuration Panel - Allow Column Dragging](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2Fv8NyyoupJ0lcSqptEayo%2Fdragging-panel-conf.png?alt=media\&token=982a2a66-6959-4cc4-8515-2cbcd9d9beca)

Let us group the DkGrid rows by the **Country** and **Gender** columns.

![Grouped by Country and Gender columns](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FTqzaUavUyqJlN4ZSfJ1r%2Frow-grouping-country-gender.gif?alt=media\&token=7464bcf4-bbc8-4d87-be70-655651ca3f3c)

### Custom templates

As discussed in the [Column Definitions](https://docs.dikesoft.com/columns/column-definitions#templates-for-displaying-field-values) section, every column has a **default template** for displaying the corresponding field value for every row.

Every group row will take the default template for displaying its value after grouping the rows. However, you can change the default template, as you can see in the following code snippet:

{% code title="row-grouping.component.html" %}

```markup
<dk-grid id="grid-row-grouping" height="700px" #grid="dkGrid">
    <dk-grid-column
        fieldName="country"
        headerText="Country"
        dataType="Text"
        width="250"
        [displayTemplate]="country"
        groupable
        draggable>
    </dk-grid-column>
    
    <dk-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="130"
        [displayTemplate]="gender"
        draggable
        groupable>
    </dk-grid-column>
</dk-grid>

<ng-template #country let-value="fieldValue">
    <div class="grid grid-cols-country-flag gap-2">
        <img class="my-0" [src]="value | countryFlag" onerror="this.src='assets/images/flags/none.png'">
        <p [matTooltip]="value">{{ value }}</p>
    </div>
</ng-template>

<ng-template #gender let-value="fieldValue">
    <mat-icon [matTooltip]="value">{{ value }}</mat-icon>
</ng-template>
```

{% endcode %}

{% hint style="warning" %}
When defining a template to use in the group rendering, the related inner component will not pass the **row entry** object when calling the specified template.
{% endhint %}

After grouping the DkGrid rows by the **Country** and **Gender** columns, you will see the following output:

![Country and Gender columns with custom templates](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2Fwqcd6AdztFYqGZH1XJMx%2Frow-grouping-country-gender-custom-templates.png?alt=media\&token=bd5b1f0a-2192-440a-becf-56f20f871bef)

{% hint style="success" %}
We have defined a custom pipe named **countryFlag** to map the country name with its corresponding flag file.
{% endhint %}

### Clearing the group panel

You can remove columns from the group panel one by one or all of them in one action.

You can click on the **close icon** next to the column name to remove that column from the group panel. The action will **move** the column from the group panel to the **center panel**.

![Removing one column from the group panel](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FkV0wQjI2yFx7rFHAhLky%2Frow-grouping-remove-one-column.gif?alt=media\&token=b8721486-5824-4a8a-8d59-bdb950a2efb9)

Or, you can remove all columns by clicking on the **group panel icon** at the left of the panel itself. The action will **move** all the columns from the group panel to the **center panel**.

![Removing all columns from the group panel to the center panel](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2F51lOFFoaa8xaNvYZcZqR%2Frow-grouping-clear-panel.gif?alt=media\&token=1c83b114-9d69-414a-ab5d-0ab754f274ac)

## Group Selection

You can open the [Floating Configuration Panel](https://docs.dikesoft.com/overview#floating-configuration-panel) and click on the **Allow Selection** checkbox to enable selection.

![Floating Configuration Panel - Allow Selection](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FR0ZZq1Pf1grFV8IN86tZ%2Fselection-panel-conf.png?alt=media\&token=1756c6f8-11e7-499d-a420-228c9c2e57cb)

{% hint style="success" %}
See the [Row Selection - Group Selection](https://docs.dikesoft.com/row-selection#group-selection) section for further details about group selection.
{% endhint %}

## Row Grouping using the API

You can use the **column API** to move columns to, from, or inside the group panel, and you can use the **rowGrouping API** to clear columns from the group panel.

{% hint style="info" %}
When you group the DkGrid rows by some columns, it is enough to define them as **draggable**, **groupable**, and not **locked** when using the **API**. Therefore, it does not matter if you do not provide the input property <mark style="color:orange;">`allowColumnDragging`</mark>.
{% endhint %}

Before using the **API**, you must retrieve the corresponding DkGrid instance by querying the component's view.

{% tabs %}
{% tab title="row-grouping.component.html" %}

```markup
<dk-grid id="grid-row-grouping" height="700px" #grid="dkGrid">
</dk-grid>
```

{% endtab %}

{% tab title="row-grouping.component.ts" %}

```typescript
@Component({
  selector: 'row-grouping',
  templateUrl: './row-grouping.component.html',
  styleUrls: ['./row-grouping.component.scss'],

  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class RowGroupingComponent implements OnInit, OnDestroy {
  // Retrieve the DikeGridComponent<T> instance from the view:
  @ViewChild('grid') dkGrid: DkGridComponent<Employee>;
  // ...
}
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
The **Row-Grouping API** is an instance of type <mark style="color:green;">`DkGridRowGrouping`</mark> under the [<mark style="color:green;">`DikeGridComponent`</mark>](https://docs.dikesoft.com/reference/components/dkgridcomponent) through the **read-only** property named `rowGrouping`.
{% endhint %}

The **rowGrouping API** has the following method:

| Method               | Description                                                                 |
| -------------------- | --------------------------------------------------------------------------- |
| `clearRowGrouping()` | This method will move all columns from the group panel to the center panel. |

{% hint style="success" %}
For further details, see the [<mark style="color:green;">`DikeGridRowGrouping`</mark>](https://docs.dikesoft.com/reference/dkgrid-api/dkgridrowgrouping) definition.
{% endhint %}

{% hint style="success" %}
For further details about the **column API**, see the [<mark style="color:green;">`DikeGridColumnDef`</mark>](https://docs.dikesoft.com/reference/dkgrid-api/dkgridcolumndef) definition.
{% endhint %}

To see the **API** in action, consider the following UI additions:

{% tabs %}
{% tab title="row-grouping.component.html" %}

```markup
<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <mat-form-field appearance="fill" class="flex-none w-56 m-2">
        <mat-label>Content panels</mat-label>
        <mat-select [formControl]="columnControl" required>
            <mat-select-trigger>
                <div class="w-40 flex flex-row items-center justify-between">
                    <div>{{ columnControl.value?.headerText }}</div>
                    <mat-icon *ngIf="columnControl.value && columnControl.value.draggable && columnControl.value.groupable && !columnControl.value.locked">list</mat-icon>
                </div>
            </mat-select-trigger>
            <mat-option *ngFor="let column of contentColumns" [value]="column">
                <div class="flex flex-row items-center justify-between">
                    <div>{{ column.headerText }}</div>
                    <mat-icon *ngIf="column.draggable && column.groupable && !column.locked">list</mat-icon>
                </div>
            </mat-option>
        </mat-select>
    </mat-form-field>

    <mat-form-field appearance="fill" class="flex-none w-56 m-2">
        <mat-label>Group panel</mat-label>
        <mat-select [formControl]="groupByColumnControl" required>
            <mat-option *ngFor="let column of groupColumns" [value]="column">
                {{ column.headerText }}
            </mat-option>
        </mat-select>
    </mat-form-field>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!columnControl.valid"
            (click)="onGroupBy()">Group by
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!groupByColumnControl.valid"
            (click)="onMoveColumn()">Move to center panel
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!isDikeGridGroupedBy"
            (click)="onClearGroupPanel()">Clear group panel
        </button>
    </div>
</div>

<dike-grid id="grid-row-grouping" height="700px" #grid="dkgGrid">
</dike-grid>

```

{% endtab %}

{% tab title="row-grouping.component.ts" %}

```typescript
onGroupBy(): void {
  if (this.columnControl.valid) {
    const contentPanelColumn = this.columnControl.value as DikeColumnDef;
    this.dikeGrid.columnDef.moveColumnIntoPanel(contentPanelColumn, 'groupPanel');
  }
}

onMoveColumn(): void {
  if (this.groupByColumnControl.valid) {
    const groupPanelColumn = this.groupByColumnControl.value as DikeColumnDef;
    this.dikeGrid.columnDef.moveColumnIntoPanel(groupPanelColumn, 'centerPanel');
  }
}

onClearGroupPanel(): void {
  this.dikeGrid.rowGrouping.clearRowGrouping();
}
```

{% endtab %}
{% endtabs %}

The previous HTML code generates the following output:

![Row Grouping using the API](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2Fl0XxKjAKyE9HJ79ROVMe%2Frow-grouping-ui-for-api.png?alt=media\&token=366f0037-aaba-4d9d-ae79-e74e8af59788)

With the previous UI, you can do the following actions:

1. First, you can choose a column from the **Content panels** dropdown control. **Draggable**, **groupable**, and **not locked** columns have an icon indicating they can group the DikeGrid rows. After selecting a column, you can click on the **Group by** button, moving the column to the group panel.
2. The **Group panel** dropdown control contains the columns in the group panel. You can choose a column and move it to the center panel by clicking on the related button.
3. You can click on the **Clear group panel** button to move all the columns from the group panel to the center panel.

Be aware that we left all the columns from the content panels enabled, even the column group named **Complete Name**.

{% hint style="warning" %}
You cannot move column groups to the group panel from the UI. Nevertheless, you can use the **column API** to move column groups to the group panel. The column API takes all the data columns from the given column group and inserts those defined as **groupable**, **draggable**, and **not locked**.
{% endhint %}

It is essential to notice that we are **listening** to any change in the **DikeGrid's columns**, attaching a callback to the `contentPanelsColumnsChange` and `groupPanelColumnsChange` events.

{% tabs %}
{% tab title="row-grouping.component.html" %}

```markup
<dike-grid id="grid-row-grouping" height="700px" #grid="dkgGrid"
    (contentPanelsColumnsChange)="onContentColumnsChange($event)"
    (groupPanelColumnsChange)="onGroupColumnsChange($event)">
</dike-grid>
```

{% endtab %}

{% tab title="row-grouping.component.ts" %}

```typescript
onContentColumnsChange(columns: DikeColumnDef[]): void {
  this.contentColumns = this.flatColumns(columns);
  // Clear the selected column:
  this.columnControl.patchValue(null);
}

onGroupColumnsChange(columns: DikeColumnDef[]): void {
  this.groupColumns = this.flatColumns(columns);
  // Clear the selected column:
  this.groupByColumnControl.patchValue(null);
  // Update the flag to let us know if the DikeGrid rows are grouped:
  this.isDikeGridGroupedBy = columns.length > 0;
}

```

{% endtab %}
{% endtabs %}

Every time we receive a new set of columns, we flat them into a single array, invoking the method `flatColumns()`. So indeed, we are **flattening** the **column groups**, traversing them **recursively**.

{% code title="row-grouping.component.ts" %}

```typescript
private flatColumns(columns: DikeColumnDef[]): DikeColumnDef[] {
  return columns.reduce((accum, column) => {
    if (isDikeGroupColumnDef(column) && !!column.children && column.children.length > 0) {
      return [ ...accum, column, ...this.flatColumns(column.children) ];
    }

    return [ ...accum, column ];
  }, [ ]);
}

```

{% endcode %}

If you see the items of the **Content panels** **dropdown** control, you see the columns **Employee Id**, **Country**, **Complete Name**, **Name**, **Surname**, etc.

![Flattening column groups](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2Fz5aiHAOCpZfmXvYvEkxi%2Frow-grouping-flattening-groups.png?alt=media\&token=80e8634e-f54c-4a45-b67e-251ef45c4231)

## Customizing the group panel

You can change the **group panel** **height**, the **height of the columns** displayed in the group panel, and the **Row-Grouping indent width**. Indeed, you can hide the Row-Grouping indent.

{% hint style="success" %}
For further details, see the [Grid Structure - Group panel section](https://docs.dikesoft.com/fundamentals/grid-structure/panels#group-panel).
{% endhint %}

You can open the [Floating Configuration Panel](https://docs.dikesoft.com/overview#floating-configuration-panel) for the **live demo** and change any mentioned properties.

## Empty values

When the DikeGrid instance groups the rows, the following values are considered empties:

| DikeColumnDataType  | Values                                                                      |
| ------------------- | --------------------------------------------------------------------------- |
| `Text` and `Binary` | `null`, `undefined`, and empty <mark style="color:green;">`strings`</mark>. |
| `Numeric`           | `null`, `undefined`, and <mark style="color:green;">`NaN`</mark> values.    |
| `Date`              | `null`, `undefined`, and <mark style="color:red;">`Invalid Dates`</mark>.   |

{% hint style="info" %}
We recommend you define the **getter function** for the columns you define. For further details, see the [Column Definitions](https://docs.dikesoft.com/columns/column-definitions#retrieving-and-updating-a-field-value) section.
{% endhint %}

## Row-Grouping events

Regarding row grouping operation, the DikeGrid instance emits the following events:

| Event                     | Description                                                                                |
| ------------------------- | ------------------------------------------------------------------------------------------ |
| `groupPanelColumnsChange` | Every time the user moves a column to, from, and inside the group panel, this event emits. |
| `collapseGroupRowChange`  | It emits when the user opens or closes a group row.                                        |

We listen to these two events at the grid scope:

{% tabs %}
{% tab title="row-grouping.component.html" %}

```markup
<dike-grid id="grid-row-grouping" height="700px" #grid="dkgGrid"
    (groupPanelColumnsChange)="onGroupColumnsChange($event)"
    (collapseGroupRowChange)="onCollapseGroupRowChange($event)">
</dike-grid>
```

{% endtab %}

{% tab title="row-grouping.component.ts" %}

```typescript
onGroupColumnsChange(columns: DikeColumnDef[]): void {
  this.groupColumns = this.flatColumns(columns);
  // Clear the selected column:
  this.groupByColumnControl.patchValue(null);
  // Update the flag to let us know if the DikeGrid rows are grouped:
  this.isDikeGridGroupedBy = columns.length > 0;
}
  
onCollapseGroupRowChange(event: DikeGroupRowCollapseEvent<Employee>): void {
  console.log('DikeGroupRowCollapseEvent: ', event);
}

```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can listen to these events from the [<mark style="color:green;">`DikeGridRowGrouping`</mark>](https://docs.dikesoft.com/reference/dkgrid-api/dkgridrowgrouping#events) instance.
{% endhint %}

{% hint style="success" %}
Please, open the **dev console** to see the output of the `collapseGroupRowChange` event.
{% endhint %}

## Summary

Firstly, you must allow the **Row-Grouping** operation at the grid scope by providing an input property named <mark style="color:orange;">`allowRowGrouping`</mark>. Then, to group the DikeGrid rows by a column, you must define that column as **draggable**, **groupable**, and **not locked**.

For row grouping, through the **UI**, you must provide the input property named <mark style="color:orange;">`allowColumnDragging`</mark>.

### Complete code for this section

{% tabs %}
{% tab title="row-grouping.component.html" %}

```markup
<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <mat-form-field appearance="fill" class="flex-none w-56 m-2">
        <mat-label>Content panels</mat-label>
        <mat-select [formControl]="columnControl" required>
            <mat-select-trigger>
                <div class="w-40 flex flex-row items-center justify-between">
                    <div>{{ columnControl.value?.headerText }}</div>
                    <mat-icon *ngIf="columnControl.value && columnControl.value.draggable && columnControl.value.groupable && !columnControl.value.locked">list</mat-icon>
                </div>
            </mat-select-trigger>
            <mat-option *ngFor="let column of contentColumns" [value]="column">
                <div class="flex flex-row items-center justify-between">
                    <div>{{ column.headerText }}</div>
                    <mat-icon *ngIf="column.draggable && column.groupable && !column.locked">list</mat-icon>
                </div>
            </mat-option>
        </mat-select>
    </mat-form-field>

    <mat-form-field appearance="fill" class="flex-none w-56 m-2">
        <mat-label>Group panel</mat-label>
        <mat-select [formControl]="groupByColumnControl" required>
            <mat-option *ngFor="let column of groupColumns" [value]="column">
                {{ column.headerText }}
            </mat-option>
        </mat-select>
    </mat-form-field>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!columnControl.valid"
            (click)="onGroupBy()">Group by
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!groupByColumnControl.valid"
            (click)="onMoveColumn()">Move to center panel
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            [disabled]="!isDikeGridGroupedBy"
            (click)="onClearGroupPanel()">Clear group panel
        </button>
    </div>
</div>

<dike-grid id="grid-row-grouping" height="700px" #grid="dkgGrid"
    [displayRowId]="gridProperties.displayRowId"
    [gridElevation]="gridProperties.matElevation"
    [gridElevationValue]="gridProperties.elevationValue"
    [striped]="gridProperties.stripeRows"
    [verticalRowLines]="gridProperties.verticalRowLines"

    allowRowGrouping
    [allowColumnDragging]="gridProperties.allowColumnDragging"
    [allowSelection]="gridProperties.allowSelection"

    (contentPanelsColumnsChange)="onContentColumnsChange($event)"
    (groupPanelColumnsChange)="onGroupColumnsChange($event)"
    (collapseGroupRowChange)="onCollapseGroupRowChange($event)"

    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dike-grid-column>

    <dike-grid-column
        fieldName="country"
        headerText="Country"
        dataType="Text"
        width="250"
        [displayTemplate]="country"
        groupable
        draggable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            groupable
            draggable>
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            draggable>
        </dike-grid-column>

    </dike-grid-column>

    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="130"
        [displayTemplate]="gender"
        draggable
        groupable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="age"
        headerText="Age"
        dataType="Numeric"
        contentAlign="center"
        width="100"
        draggable
        groupable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="email"
        headerText="Email"
        dataType="Text"
        width="300">
    </dike-grid-column>

    <dike-grid-column
        fieldName="hireDate"
        headerText="Hire Date"
        dataType="Date"
        width="150">
    </dike-grid-column>

</dike-grid>

<ng-template #country let-value="fieldValue">
    <div class="grid grid-cols-country-flag gap-2">
        <img class="my-0" [src]="value | countryFlag" onerror="this.src='assets/images/flags/none.png'">
        <p [matTooltip]="value">{{ value }}</p>
    </div>
</ng-template>

<ng-template #gender let-value="fieldValue">
    <mat-icon [matTooltip]="value">{{ value }}</mat-icon>
</ng-template>

```

{% endtab %}

{% tab title="row-grouping.component.ts" %}

```typescript
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';

import { Subscription } from 'rxjs';

import { DikeColumnDef, DikeGridComponent, DikeGridDataSourceInput, DikeGroupRowCollapseEvent, isDikeGroupColumnDef } from '@dikesoft/angular-data-grid';
import { DikeGridProperties } from 'app/core/config/dike-grid.properties';
import { Employee } from 'app/mock-api/common/employees/data.model';

import { DikeGridConfig } from 'app/services/dike-grid.config.service';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'row-grouping',
  templateUrl: './row-grouping.component.html',
  styleUrls: ['./row-grouping.component.scss'],

  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class RowGroupingComponent implements OnInit, OnDestroy {
  // Retrieve the DikeGridComponent<T> instance from the view:
  @ViewChild('grid') dikeGrid: DikeGridComponent<Employee>;

  dkgDataSource: DikeGridDataSourceInput<Employee>;
  gridProperties: DikeGridProperties;

  columnControl: FormControl;
  groupByColumnControl: FormControl;

  contentColumns: DikeColumnDef[];
  groupColumns: DikeColumnDef[];
  isDikeGridGroupedBy: boolean;

  private changeGridPropertiesSubscription: Subscription = Subscription.EMPTY;

  constructor(
    private cdr: ChangeDetectorRef,
    private gridConfig: DikeGridConfig,
    private sampleData: SampleData) {

    this.isDikeGridGroupedBy = false;
  }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000);
    // Listening to any config property change:
    this.setChangeGridPropertiesSubscription();

    this.columnControl = new FormControl(null, Validators.required);
    this.groupByColumnControl = new FormControl(null, Validators.required);
  }

  ngOnDestroy(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
  }

  onContentColumnsChange(columns: DikeColumnDef[]): void {
    this.contentColumns = this.flatColumns(columns);
    // Clear the selected column:
    this.columnControl.patchValue(null);
  }

  onGroupColumnsChange(columns: DikeColumnDef[]): void {
    this.groupColumns = this.flatColumns(columns);
    // Clear the selected column:
    this.groupByColumnControl.patchValue(null);
    // Update the flag to let us know if the DikeGrid rows are grouped:
    this.isDikeGridGroupedBy = columns.length > 0;
  }

  onGroupBy(): void {
    if (this.columnControl.valid) {
      const contentPanelColumn = this.columnControl.value as DikeColumnDef;
      this.dikeGrid.columnDef.moveColumnIntoPanel(contentPanelColumn, 'groupPanel');
    }
  }

  onMoveColumn(): void {
    if (this.groupByColumnControl.valid) {
      const groupPanelColumn = this.groupByColumnControl.value as DikeColumnDef;
      this.dikeGrid.columnDef.moveColumnIntoPanel(groupPanelColumn, 'centerPanel');
    }
  }

  onClearGroupPanel(): void {
    this.dikeGrid.rowGrouping.clearRowGrouping();
  }

  onCollapseGroupRowChange(event: DikeGroupRowCollapseEvent<Employee>): void {
    console.log('DikeGroupRowCollapseEvent: ', event);
  }

  private flatColumns(columns: DikeColumnDef[]): DikeColumnDef[] {
    return columns.reduce((accum, column) => {
      if (isDikeGroupColumnDef(column) && !!column.children && column.children.length > 0) {
        return [ ...accum, column, ...this.flatColumns(column.children) ];
      }

      return [ ...accum, column ];
    }, [ ]);
  }

  private setChangeGridPropertiesSubscription(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
    this.changeGridPropertiesSubscription = this.gridConfig.configChange.subscribe((props: DikeGridProperties) => {
      this.gridProperties = props;
      this.cdr.markForCheck();
    });
  }
}

```

{% endtab %}
{% endtabs %}
