# Row Sorting

## Live example

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

## 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 <mark style="color:orange;">`allowSorting`</mark>. Its **default** value is **false**.

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

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

{% endcode %}

{% hint style="info" %}
You can change the value of the <mark style="color:orange;">`allowSorting`</mark> property at **runtime**.
{% endhint %}

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

![Floating Configuration Panel - Sorting](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FiLAwaKAtLVpzqnVPqLnQ%2Fsorting-panel-conf.png?alt=media\&token=2842ef4c-7dac-42d3-b571-6056e4b6be62)

## 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**.

{% hint style="info" %}
You can only make **sortable** data columns, not column groups.
{% endhint %}

See the following column configuration:

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

```markup
<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>
```

{% endcode %}

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:

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

```typescript
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);
    }
  }
}
```

{% endcode %}

As you can see, once you have got the column you want to set as **sortable** or **non-sortable**, use the <mark style="color:green;">`DikeGridColumnDef`</mark> service instance to change the column state.

{% hint style="success" %}
Before using the **column API**, you must grab the instance of the [<mark style="color:green;">`DikeGridColumnDef`</mark>](https://docs.dikesoft.com/reference/dkgrid-api/dkgridcolumndef) service.
{% endhint %}

## 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.

![Sorting by Name column clicking on the column header](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2Fn0V2XXpeSoopQ0hwCTcd%2Frow-sorting-column-header.gif?alt=media\&token=42403f5a-821d-47e8-971c-66135c506b40)

### Column Context Menu

When you define a column as **sortable**, you will see the sorting submenu in the [Column Context Menu](https://docs.dikesoft.com/fundamentals/grid-structure/column-context-menu). Then, you will see the sorting options.

![Sorting By Name column using the Column Context Menu](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FfT6OPt2E3O95g9k1jUww%2Frow-sorting-context-menu.gif?alt=media\&token=9add6add-fd97-48d8-bd43-d7ac67ca69ec)

## 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.

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

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

{% endtab %}

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

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

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

{% endtab %}
{% endtabs %}

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

The **sorting API** has the following methods:

| Method                 | Description                                                                                   |
| ---------------------- | --------------------------------------------------------------------------------------------- |
| `sortBy()`             | It sorts the DikeGrid rows by the given column in the given direction.                        |
| `isDikeGridSortedBy()` | It evaluates if the DikeGrid is sorted by the given column.                                   |
| `getCurrentSortable()` | It returns the column and the direction of the sorting operation. Otherwise, it returns null. |
| `clearSorting()`       | It removes the current sorting operation.                                                     |

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

{% hint style="info" %}
You can sort the DikeGrid rows only by **one** column **sortable** at a time.
{% endhint %}

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

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

```markup
<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>

```

{% endtab %}

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

```typescript
onSelectionChange(data: MatSelectChange): void {
  const column = data.value as DikeColumnDef;

  if (isDikeDataColumnDef(column)) {
    if (!column.sortable) {
      this.rowSortingForm.get('direction').disable();

    } else {
      this.rowSortingForm.get('direction').enable();
    }
  }
}

onSortBy(): void {
  if (this.rowSortingForm.valid) {
    const column = this.rowSortingForm.get('column').value as DikeColumnDef;
    const direction = this.rowSortingForm.get('direction').value as 'asc' | 'desc';

    // if the DikeGrid instance is sorted, get the current columns and the sort direction:
    const currentSortable = this.dikeGrid.sorting.getCurrentSortable();

    /**
     * We will sort the DikeGrid rows, if only if:
     *
     *    1. The DikeGrid is not sorted.
     *    2. Or, the DikeGrid is sorted but the selected column is different than the current column.
     *    3. Or, the DikeGrid is sorted by the selected column but the selected direction is different.
     */
    if (isDikeDataColumnDef(column) &&
      (!currentSortable || currentSortable.sortedColumn.columnId !== column.columnId || currentSortable.type !== direction)) {
      this.dikeGrid.sorting.sortBy(column, direction);
    }
  }
}

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);
    }
  }
}

```

{% endtab %}
{% endtabs %}

The previous HTML code generates the following output:

![Row sorting using the API](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FR41TB87TR8SK1E3Hdjfy%2Frow-sorting-ui-for-api.png?alt=media\&token=e256d47f-0355-4733-9c10-fbe1cc951fd2)

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 [<mark style="color:green;">`DikeGridComponent`</mark>](https://docs.dikesoft.com/reference/components/dkgridcomponent).

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

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

{% endtab %}

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

```typescript
onColumnsChange(columns: DikeColumnDef[]): void {
    this.gridColumns = this.flatColumns(columns);
    // Clear selection:
    this.rowSortingForm.patchValue({ column: null, direction: '' });
}
```

{% 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-sorting.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 content of the **dropdown** control, you see the columns **Employee Id**, **Personal Info** group, **Complete Name** group, then **Name** and **Surname** columns, etc.

![Flattening column groups](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FfUsQ68waYlfQFsPSrfx3%2Frow-sorting-flattening-groups.png?alt=media\&token=5d28022e-d685-42ee-867f-d34b60dd6dbf)

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.

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

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

{% endtab %}

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

```typescript
onSortChange(sortedBy: DikeColumnSortEvent<Employee>): void {
  console.log('Sort change: ', sortedBy);
}
```

{% endtab %}
{% endtabs %}

The emitted object is of type <mark style="color:green;">`DikeColumnSortEvent`</mark>, which contains the **column** and the **direction** of the current sorting operation.

{% hint style="success" %}
Open the **dev console** to see the output of the `sortChange` event.
{% endhint %}

{% hint style="info" %}
You can also listen to the `sortChange` event from the [<mark style="color:green;">`DikeGridSorting`</mark>](https://docs.dikesoft.com/reference/dkgrid-api/dkgridsorting#events) instance.
{% endhint %}

## Summary

To perform the sorting operation, you must allow it by providing an input property named <mark style="color:orange;">`allowSorting`</mark>. 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

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

```markup
<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>

```

{% endtab %}

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

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

import { Subscription } from 'rxjs';

import { DikeColumnDef, DikeColumnSortEvent, DikeGridComponent, 
  DikeGridDataSourceInput, isDikeDataColumnDef, 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-sorting',
  templateUrl: './row-sorting.component.html',
  styleUrls: ['./row-sorting.component.scss'],

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

  dkgDataSource: DikeGridDataSourceInput<Employee>;
  gridProperties: DikeGridProperties;

  gridColumns: DikeColumnDef[];
  rowSortingForm: FormGroup;
  columnControl: FormControl;

  private changeGridPropertiesSubscription: Subscription = Subscription.EMPTY;

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

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

  onSelectionChange(data: MatSelectChange): void {
    const column = data.value as DikeColumnDef;

    if (isDikeDataColumnDef(column)) {
      if (!column.sortable) {
        this.rowSortingForm.get('direction').disable();

      } else {
        this.rowSortingForm.get('direction').enable();
      }
    }
  }

  onSortBy(): void {
    if (this.rowSortingForm.valid) {
      const column = this.rowSortingForm.get('column').value as DikeColumnDef;
      const direction = this.rowSortingForm.get('direction').value as 'asc' | 'desc';

      // if the DikeGrid instance is sorted, get the current columns and the sort direction:
      const currentSortable = this.dikeGrid.sorting.getCurrentSortable();

      /**
       * We will sort the DikeGrid rows, if only if:
       *
       *    1. The DikeGrid is not sorted.
       *    2. Or, the DikeGrid is sorted but the selected column is different than the current column.
       *    3. Or, the DikeGrid is sorted by the selected column but the selected direction is different.
       */
      if (isDikeDataColumnDef(column) &&
        (!currentSortable || currentSortable.sortedColumn.columnId !== column.columnId || currentSortable.type !== direction)) {
        this.dikeGrid.sorting.sortBy(column, direction);
      }
    }
  }

  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);
      }
    }
  }

  onSortChange(sortedBy: DikeColumnSortEvent<Employee>): void {
    console.log('Sort change: ', sortedBy);
  }

  onColumnsChange(columns: DikeColumnDef[]): void {
    this.gridColumns = this.flatColumns(columns);
    // Clear selection:
    this.rowSortingForm.patchValue({ column: null, direction: '' });
  }

  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 createForm(): void {
    this.columnControl = new FormControl(null, Validators.required);

    this.rowSortingForm = new FormGroup({
      column: this.columnControl,
      direction: new FormControl({ value: '', disabled: false }, Validators.required),
    });
  }

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

```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dikesoft.com/rows/row-sorting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
