Row Sorting

This section describes how you can sort the DikeGrid rows.

Live example

Row Sorting live example.

Allowing the sorting operation

To allow the user to sort the DikeGrid rows, you must set a flag at the grid scope by providing an input property named allowSorting. Its default value is false.

row-sorting.component.html
<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid"
    [allowSorting]="gridProperties.allowSorting">
</dike-grid>

You can change the value of the allowSorting property at runtime.

Open the Floating Configuration Panel for the live example and mark the Allow Sorting checkbox.

Sortable columns

If you want the user to sort the DikeGrid rows by a column, mark the column as sortable. Its default value is false.

You can only make sortable data columns, not column groups.

See the following column configuration:

row-sorting.component.html
<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid"
    [allowSorting]="gridProperties.allowSorting">
    
    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="personalInfoGroup"
        headerText="Personal Info">

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

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

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

        </dike-grid-column>

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

        <dike-grid-column
            fieldName="age"
            headerText="Age"
            dataType="Numeric"
            contentAlign="center"
            width="100"
            sortable>
        </dike-grid-column>
    </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"
       sortable>
    </dike-grid-column>
    
</dike-grid>

We have the following sortable columns with the previous configuration: Name and Surname under the Complete Name group, Age column under the Personal Info group, and the Hire Date column.

You can make a column sortable at runtime using the corresponding API. For example, see the following code snippet:

row-sorting.component.ts
onSetColumnSortable(): void {
  if (this.columnControl.valid) {
    // Get the selected column:
    const column = this.columnControl.value as DikeColumnDef;

    if (isDikeDataColumnDef(column)) {
      // Toggle the sortable flag for the selected column:
      this.dikeGrid.columnDef.setColumnSortable(column, !column.sortable);
    }
  }
}

As you can see, once you have got the column you want to set as sortable or non-sortable, use the DikeGridColumnDef service instance to change the column state.

Before using the column API, you must grab the instance of the DikeGridColumnDef service.

Sorting rows through the UI

Once you define columns as sortable, you can sort the DikeGrid rows by these sortable columns.

Clicking on the column header

You can sort the DikeGrid rows by clicking on the column header.

When you have clicked on the column header of a sortable column, you will see an arrow that indicates the direction of the sorting operation.

Column Context Menu

When you define a column as sortable, you will see the sorting submenu in the Column Context Menu. Then, you will see the sorting options.

DikeGrid Sorting API

You can sort the DikeGrid rows using the sorting API.

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

<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid">
</dike-grid>

The sorting API is an instance of type DikeGridSorting under the DikeGridComponent through the read-only property named sorting.

The sorting API has the following methods:

For further details, see the DikeGridSorting definition.

You can sort the DikeGrid rows only by one column sortable at a time.

To see the use of the sorting API, we have created the following UI:

<form [formGroup]="rowSortingForm"
  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>Columns</mat-label>
      <mat-select [formControl]="columnControl" (selectionChange)="onSelectionChange($event)" 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.sortable">sort_by_alpha</mat-icon>
            </div>
          </mat-select-trigger>
          <mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!!column.children">
              <div class="flex flex-row items-center justify-between">
                <div>{{ column.headerText }}</div>
                <mat-icon *ngIf="column.sortable">sort_by_alpha</mat-icon>
              </div>
          </mat-option>
      </mat-select>
    </mat-form-field>

  <mat-radio-group class="flex-none w-56 m-2 flex flex-row justify-around"
      #radioDirections="matRadioGroup" formControlName="direction" required>
      <mat-radio-button class="my-2" value="asc">asc</mat-radio-button>
      <mat-radio-button class="my-2" value="desc">desc</mat-radio-button>
  </mat-radio-group>

  <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]="!rowSortingForm.valid || radioDirections.disabled"
          (click)="onSortBy()">Sort by
      </button>

      <button mat-raised-button
          class="flex-none w-56 my-2"
          color="primary"
          [disabled]="!columnControl.valid"
          (click)="onSetColumnSortable()">Set column {{ columnControl.value?.sortable ? 'non-' : '' }}sortable
      </button>
  </div>
</form>

<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid">
</dike-grid>

The previous HTML code generates the following output:

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

  1. You can choose any data column from the dropdown control. Sortable columns have an icon indicating they are sortable.

  2. You can change the sortable state of a data column.

  3. To sort the DikeGrid rows, you must select the direction of the sorting operation. Then click on the Sort By button.

It is essential to notice that we are listening to any change in the DikeGrid's columns, attaching a callback to the columnsChange output property from the DikeGridComponent.

<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid"
    (columnsChange)="onColumnsChange($event)">
</dike-grid>

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.

row-sorting.component.ts
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 ];
  }, [ ]);
}

If you see the content of the dropdown control, you see the columns Employee Id, Personal Info group, Complete Name group, then Name and Surname columns, etc.

The column groups are disabled, such as Personal Info and Complete Name.

Sort event

Every time we sort the DikeGrid rows, the DikeGrid instance emits the related event.

<dike-grid id="grid-row-sorting" height="650px" #grid="dkgGrid"
    (sortChange)="onSortChange($event)">
</dike-grid>

The emitted object is of type DikeColumnSortEvent, which contains the column and the direction of the current sorting operation.

Open the dev console to see the output of the sortChange event.

You can also listen to the sortChange event from the DikeGridSorting instance.

Summary

To perform the sorting operation, you must allow it by providing an input property named allowSorting. Then, when creating columns, you can define them as sortable. Nevertheless, you can change their state at runtime using the related API. You can perform the sorting operation through the UI or the sorting API.

Complete code for this section

<form [formGroup]="rowSortingForm"
  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>Columns</mat-label>
      <mat-select [formControl]="columnControl" (selectionChange)="onSelectionChange($event)" 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.sortable">sort_by_alpha</mat-icon>
            </div>
          </mat-select-trigger>
          <mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!!column.children">
              <div class="flex flex-row items-center justify-between">
                <div>{{ column.headerText }}</div>
                <mat-icon *ngIf="column.sortable">sort_by_alpha</mat-icon>
              </div>
          </mat-option>
      </mat-select>
    </mat-form-field>
    
      <mat-radio-group class="flex-none w-56 m-2 flex flex-row justify-around"
          #radioDirections="matRadioGroup" formControlName="direction" required>
          <mat-radio-button class="my-2" value="asc">asc</mat-radio-button>
          <mat-radio-button class="my-2" value="desc">desc</mat-radio-button>
      </mat-radio-group>
    
      <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]="!rowSortingForm.valid || radioDirections.disabled"
              (click)="onSortBy()">Sort by
          </button>

          <button mat-raised-button
              class="flex-none w-56 my-2"
              color="primary"
              [disabled]="!columnControl.valid"
              (click)="onSetColumnSortable()">Set column {{ columnControl.value?.sortable ? 'non-' : '' }}sortable
          </button>
      </div>
</form>

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

    (columnsChange)="onColumnsChange($event)"
    (sortChange)="onSortChange($event)"

    [allowSorting]="gridProperties.allowSorting"
    [datasource]="dkgDataSource">

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

    <dike-grid-column
        fieldName="personalInfoGroup"
        headerText="Personal Info">

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

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

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

        </dike-grid-column>

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

        <dike-grid-column
            fieldName="age"
            headerText="Age"
            dataType="Numeric"
            contentAlign="center"
            width="100"
            sortable>
        </dike-grid-column>
    </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"
        sortable>
    </dike-grid-column>
</dike-grid>

Last updated