Column Pinning

Once you have defined a column as draggable, you can make it non-draggable at runtime.

Live example

Column Pinning live example.

Lock/Unlock columns

When you define a column as draggable, it is possible to freeze that column by locking it.

To lock/unlock a column through the UI, you must set the flag allowColumnDragging at the grid scope.

Open the Column Context Menu for any column defined as draggable. You will see the lock/unlock icons.

Locking a column is useful when the user moves a column to the right or left panel and then freezes the column to be always visible. Even though the user can lock a column in the center panel, it makes more sense to freeze columns in the left or right panels.

The user can not move locked columns, and other columns can not occupy their place when dragging operation occurs.

Defining frozen columns

To not allow a user to move a column nor lock/unlock it, define the column as non-draggable.

Only draggable columns are susceptible to being locked/unlocked.

Consider the following column configuration:

column-pinning.component.html
<dike-grid id="grid-col-pinning" height="650px" #grid="dkgGrid"
    [allowColumnDragging]="gridProperties.allowColumnDragging">

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

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

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

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

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

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

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

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

        <dike-grid-column
            fieldName="gender"
            headerText="Gender"
            dataType="Binary"
            width="130"
            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>

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

With this configuration, we have:

  1. All columns are draggable except the Employee Id column, the Name column in the root group, and the Surname under the Complete Name column group.

  2. We locked the columns Email and Name under the Complete Name group.

  3. Finally, we defined the Employee Id column in the left panel, which is non-draggable. The user can not move or lock/unlock this column.

As you can see, the user can not move the Employee Id column and will not lock/unlock it. If you try to move the column, you will see an icon that indicates the user cannot move that column.

Lock/Unlock column using the API

You can lock/unlock columns using the column API.

Remember, to use the column API, you must grab the instance of the DikeGridColumnDefservice.

You use lockColumn() and unlockColumn() methods for locking and unlocking, respectively.

Although you do not set the flag allowColumnDragging, you can lock/unlock a column using the API, but you must define the column as draggable.

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

column-pinning.component.html
<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>Columns</mat-label>
        <mat-select [formControl]="selectedColumn" required
            (selectionChange)="onSelectionChange($event)">
            <mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!column.draggable">
                {{ column.headerText }}
            </mat-option>
        </mat-select>
    </mat-form-field>
    
    <button mat-raised-button
        class="flex-none w-56 my-2"
        color="primary"
        [disabled]="!selectedColumn.valid"
        (click)="onChangeLocking()">{{ isColumnLocked ? 'unlock': 'lock' }} column
    </button>
</div>

The generated output is:

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

  1. You can choose any defined column as draggable. It includes column groups.

  2. Depending on the locked state, the button next to the dropdown control will display the lock or unlock label.

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-col-pinning" 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.

column-pinning.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, Name, Personal Info group, Complete Name group, then Name and Surname columns, etc.

The non-draggable columns are disabled, such as Employee Id, Name in the root group, and Surname, under the Complete Name group.

Events when Locking/Unlocking columns

When you lock or unlock a column, the DikeGrid instance emits the related event.

<dike-grid id="grid-col-pinning" height="650px" #grid="dkgGrid"
    (columnLockedChange)="onColumnLockedChange($event)"
    (columnUnLockedChange)="onColumnUnLockedChange($event)">
</dike-grid>

You can also listen to the columnLockedChange and columnUnLockedChange events from the DikeGridColumnDefinstance.

Both events emit the locked/unlocked column. Notice that the sent column is of type DikeColumnDef because you can lock/unlock column groups, not only data columns.

Open the dev console to see the locked/unlocked column.

Summary

To lock/unlock a column, you must define it as draggable. You can lock/unlock columns in any panel, even in the group panel, but freezing columns in the left or right panels makes more sense.

Complete code for this section

<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>Columns</mat-label>
        <mat-select [formControl]="selectedColumn" required
            (selectionChange)="onSelectionChange($event)">
            <mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!column.draggable">
                {{ column.headerText }}
            </mat-option>
        </mat-select>
    </mat-form-field>

    <button mat-raised-button
        class="flex-none w-56 my-2"
        color="primary"
        [disabled]="!selectedColumn.valid"
        (click)="onChangeLocking()">{{ isColumnLocked ? 'unlock': 'lock' }} column
    </button>
</div>

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

    (columnsChange)="onColumnsChange($event)"
    (columnLockedChange)="onColumnLockedChange($event)"
    (columnUnLockedChange)="onColumnUnLockedChange($event)"

    [allowColumnDragging]="gridProperties.allowColumnDragging"
    allowRowGrouping
    [datasource]="dkgDataSource">

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

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

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

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

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

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

            <dike-grid-column
                fieldName="firstName"
                headerText="Name"
                dataType="Text"
                width="150"
                draggable
                locked>
            </dike-grid-column>
    
            <dike-grid-column
                fieldName="lastName"
                headerText="Surname"
                dataType="Text"
                width="150">
            </dike-grid-column>
        </dike-grid-column>
    
        <dike-grid-column
            fieldName="gender"
            headerText="Gender"
            dataType="Binary"
            width="130"
            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>

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

Last updated