Column Moving
This section describes how to make a column draggable and which type of movements you can do.
Live example
Column Moving live example.
Allowing column dragging
To allow the user moves a column, you must set a flag at the grid scope by providing an input DikeGrid property named allowColumnDragging
. Its default value is false.
<dike-grid id="grid-col-moving" height="650px" #grid="dkgGrid"
[allowColumnDragging]="gridProperties.allowColumnDragging">
</dike-grid>
You can open the Floating Configuration Panel of the live demo and change the value of the property allowColumnDragging
.

Draggable Columns
You can make a column movable by providing a property named draggable
. Its default value is false.
Be aware that you can not change the draggable
property at runtime. Use the locked
property instead if you want the user not to move a column at runtime. For more details, see the Column Pinning section.
Let us set the following column configuration:
<dike-grid id="grid-col-moving" height="650px" #grid="dkgGrid"
allowRowGrouping
allowColumnDragging>
<dike-grid-column
fieldName="employeeId"
headerText="Employee Id"
dataType="Text"
width="350"
order="0"
draggable>
</dike-grid-column>
<dike-grid-column
fieldName="firstName"
headerText="Name"
dataType="Text"
width="150"
order="2">
</dike-grid-column>
<dike-grid-column
fieldName="lastName"
headerText="Surname"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
order="1"
resizable
draggable
groupable>
</dike-grid-column>
<dike-grid-column
fieldName="personalInfoGroup"
headerText="Personal Info"
order="0"
resizable
draggable>
<dike-grid-column
fieldName="completeNameGroup"
headerText="Complete Name"
draggable>
<dike-grid-column
fieldName="firstName"
headerText="Name"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
<dike-grid-column
fieldName="lastName"
headerText="Surname"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
</dike-grid-column>
<dike-grid-column
fieldName="gender"
headerText="Gender"
dataType="Binary"
width="110"
minWidth="50"
maxWidth="200"
resizable
draggable
groupable>
</dike-grid-column>
<dike-grid-column
fieldName="age"
headerText="Age"
dataType="Numeric"
contentAlign="center"
width="85"
minWidth="50"
maxWidth="120"
resizable
draggable
groupable>
</dike-grid-column>
</dike-grid-column>
<dike-grid-column
fieldName="hireDate"
headerText="Hire Date"
dataType="Date"
order="1"
draggable
groupable
panel="rightPanel">
</dike-grid-column>
</dike-grid>
With this configuration, we have:
All columns and column groups are movable except the Name column in the root group and the Name and Surname columns under the Complete Name group.
We have enabled the row grouping to move columns to the group panel. Columns Surname and Hire Date from the root group are groupable. Gender and Age columns under the Personal Info group are groupable as well.
All columns are in the center panel except the Hire Date column in the right panel.
You can move only data columns to the group panel, not column groups.
When you move a column group to the group panel using the API, the movement inserts only the descendant data columns into the group panel.
Column movements
Once we have established some columns as draggable, be aware of the valid movements a column could take.
For the description of the following movements, it will be helpful to grasp the Gutters structure of the DikeGrid.
Interchange Columns
This movement will swap two columns. The source column will take the destination column's place and vice versa. For this movement, the following rules apply:
The columns must belong to the same group of columns.
You can interchange columns that belong to the Content panels.

Move Column Before
You can move a column before another column.
Let us say that you can move a given column at the left side of the target column. The actual movement will insert the given column at the left-gutter of the target column. Therefore, consider the following rules:
Columns must belong to the same group of columns.
The target column must belong to the right panel because columns have their gutter at their left.
If the target column lives in the left, center panel, or group panel, it must be the first column because they have both gutters.

Move Column After
You can move one column after another column.
Same as before, let us say that you can move a given column at the right side of the target column. The actual movement will insert the given column at the right-gutter of the target column.
The rules are:
Columns must belong to the same group of columns.
The target column must belong to the group, left or center panel because columns have their gutter at their right.
If the target column lives in the right panel, it must be the last column because it has both gutters.

Column to panel
This movement is possible when you drag a column to the left or right grid border or use the Pinning submenu of the Column Context Menu.
Drag a column to the grid's borders
Drag a column to the left or right grid border, as you can see in the following gif.

Using the Column Context Menu
Now, click on any Column Context Menu and select a panel to move the column.

Breaking a column group
You can take a column that belongs to a column group and place it in another panel. This move grabs the column with its parent column and its parent, and so forth until the root.
The movement's outcome is a broken group. For example, we moved the Gender column to the left panel. See the final state of the Personal Info group in the following screenshot.

Unbroken column groups
If you do not want the user breaks a group, make its child columns non-draggable, as we did for Name and Surname columns under the Complete Name column group.
<dike-grid-column
fieldName="completeNameGroup"
headerText="Complete Name"
draggable>
<dike-grid-column
fieldName="firstName"
headerText="Name"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
<dike-grid-column
fieldName="lastName"
headerText="Surname"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
</dike-grid-column>
You can not move the Name column or the Surname column. You can only move those columns by dragging the Complete Name group.

Move columns using the API
You can achieve the previous movements using the column API.
The following table shows the desired movement and its related method in the column API.
Interchange Columns
swapColumns()
Move Column Before
moveColumnBefore()
Move Column After
moveColumnAfter()
Column to Panel
moveColumnIntoPanel()
To move all columns from one panel to another panel, use the method movePanelColumns()
For further details, see the DikeGridColumnDef
definition.
To see the use of the API, we have created the following UI:
<form [formGroup]="moveColumnsForm"
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>Source</mat-label>
<mat-select formControlName="source" required
(selectionChange)="onSourceSelectionChange($event)">
<mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!column.draggable || column.locked">
{{ column.headerText }}
</mat-option>
<mat-option *ngFor="let panel of gridPanels" [value]="panel">
{{ panel }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill"
class="flex-none w-56 m-2">
<mat-label>Destination</mat-label>
<mat-select formControlName="destination" required
(selectionChange)="onDestinationSelectionChange($event)">
<mat-option *ngFor="let column of destinationColumns" [value]="column" [disabled]="!column.draggable || column.locked">
{{ column.headerText }}
</mat-option>
<mat-option *ngFor="let panel of destinationPanels" [value]="panel">
{{ panel }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-radio-group class="flex-none w-40 m-2 flex flex-col"
#radioMethods="matRadioGroup" formControlName="method" required>
<mat-radio-button class="my-2" value="swap-columns">swap-columns</mat-radio-button>
<mat-radio-button class="my-2" value="column-after">column-after</mat-radio-button>
<mat-radio-button class="my-2" value="column-before">column-before</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]="radioMethods.disabled || !moveColumnsForm.valid"
(click)="onMoveColumns()">Move column(s)
</button>
<button mat-raised-button
class="flex-none w-56 my-2"
color="primary"
[disabled]="!radioMethods.disabled"
(click)="onMoveColumnsToPanel()">Move column(s) to Panel
</button>
</div>
</form>
We added the form
selector above the dike-grid
selector, generating the following output:

With the previous UI, you can do the following tasks:
You can choose the source column or the source panel from the first select control.
Depending on your selected option, the second dropdown control will have a proper destination place. For instance, if you choose a column, the destination control will contain all columns of the same group and panels the column does not live.
The radio-button group has methods that involve column between column movements.
When you select panels, the corresponding button is enabled.
It is essential to notice that we are listening to any change in the DikeGrid's columns, attaching a subscription to the columnsChange
Observable
from the DikeGridColumnDef
.
private setChangeGridColumnsSubscription(): void {
this.changeGridColumnsSubscription.unsubscribe();
this.changeGridColumnsSubscription = this.dikeGrid.columnDef.columnsChange.pipe(
map((columns: DikeColumnDef[]) => this.flatColumns(columns)),
observeOn(asapScheduler)
).subscribe((columns) => {
this.destinationColumns = null;
this.destinationPanels = null;
this.moveColumnsForm.patchValue({ source: null, destination: null, method: '' });
this.moveColumnsForm.get('method').enable();
this.gridColumns = columns;
});
}
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.
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 source dropdown control, you see the columns Hire Date, Employee Id, Personal Info group, Complete Name group, then Name and Surname columns, Gender and Age columns, etc.

Column Moving Events
Every previous movement emits an event of type DikeColumnMoveEvent
. We listen to the columnMove
event at the grid scope.
<dike-grid id="grid-col-moving" height="650px" #grid="dkgGrid"
(columnMove)="onColumnMove($event)">
</dike-grid>
You can also listen to the columnMove
event from the DikeGridColumnDef<T>
instance.
See the definition of the DikeColumnMoveEvent
interface:
interface DikeColumnMoveEvent {
type: ColumnMovement;
movedColumns: DikeColumnDef[];
beforeColumn?: DikeColumnDef;
afterColumn?: DikeColumnDef;
destinationPanel?: DikeGridPanel;
}
And the ColumnMovement
definition is:
type ColumnMovement = 'swap-columns' | 'join-column-groups' | 'column-after' | 'column-before' | 'columns-to-panel';
As you can see, some fields are not required. However, depending on the type of movement, those fields are provided.
Interchange Columns
type: swap-columns. movedColumns: The source and destination columns.
Interchange Columns
type: join-column-groups. movedColumns: The joined column group. destinationPanel: The panel the broken-destination group lives.
Move Column Before
type: column-before. movedColumns: The source column. beforeColumn: The target column. destinationPanel: The panel the target column lives.
Move Column After
type: column-after. movedColumns: The source column. afterColumn: The target column. destinationPanel: The panel the target column lives.
Column to panel
type: columns-to-panel. movedColumns: The source columns or all panel columns. destinationPanel. The provided panel is the destination panel.
You can open the dev console for the live demo and see the emitted event.
Summary
Before defining which columns will be movable, you must allow this action by providing a property named allowColumnDragging
at the grid scope. To move a column, you must define a column as draggable. You can interchange columns only from the Content panels, and you can only add data columns to the group panel. You can move columns using the Column Context Menu as well.
Complete code for this section
<form [formGroup]="moveColumnsForm"
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>Source</mat-label>
<mat-select formControlName="source" required
(selectionChange)="onSourceSelectionChange($event)">
<mat-option *ngFor="let column of gridColumns" [value]="column" [disabled]="!column.draggable || column.locked">
{{ column.headerText }}
</mat-option>
<mat-option *ngFor="let panel of gridPanels" [value]="panel">
{{ panel }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill"
class="flex-none w-56 m-2">
<mat-label>Destination</mat-label>
<mat-select formControlName="destination" required
(selectionChange)="onDestinationSelectionChange($event)">
<mat-option *ngFor="let column of destinationColumns" [value]="column" [disabled]="!column.draggable || column.locked">
{{ column.headerText }}
</mat-option>
<mat-option *ngFor="let panel of destinationPanels" [value]="panel">
{{ panel }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-radio-group class="flex-none w-40 m-2 flex flex-col"
#radioMethods="matRadioGroup" formControlName="method" required>
<mat-radio-button class="my-2" value="swap-columns">swap-columns</mat-radio-button>
<mat-radio-button class="my-2" value="column-after">column-after</mat-radio-button>
<mat-radio-button class="my-2" value="column-before">column-before</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]="radioMethods.disabled || !moveColumnsForm.valid"
(click)="onMoveColumns()">Move column(s)
</button>
<button mat-raised-button
class="flex-none w-56 my-2"
color="primary"
[disabled]="!radioMethods.disabled"
(click)="onMoveColumnsToPanel()">Move column(s) to Panel
</button>
</div>
</form>
<dike-grid id="grid-col-moving" height="650px" #grid="dkgGrid"
[displayRowId]="gridProperties.displayRowId"
[gridElevation]="gridProperties.matElevation"
[gridElevationValue]="gridProperties.elevationValue"
[striped]="gridProperties.stripeRows"
[verticalRowLines]="gridProperties.verticalRowLines"
(columnMove)="onColumnMove($event)"
[allowColumnDragging]="gridProperties.allowColumnDragging"
allowRowGrouping
[datasource]="dkgDataSource">
<dike-grid-column
fieldName="employeeId"
headerText="Employee Id"
dataType="Text"
width="350"
order="0"
draggable>
</dike-grid-column>
<dike-grid-column
fieldName="firstName"
headerText="Name"
dataType="Text"
width="150"
order="3">
</dike-grid-column>
<dike-grid-column
fieldName="lastName"
headerText="Surname"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
order="2"
resizable
draggable
groupable>
</dike-grid-column>
<dike-grid-column
fieldName="personalInfoGroup"
headerText="Personal Info"
order="1"
resizable
draggable>
<dike-grid-column
fieldName="completeNameGroup"
headerText="Complete Name"
draggable>
<dike-grid-column
fieldName="firstName"
headerText="Name"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
<dike-grid-column
fieldName="lastName"
headerText="Surname"
dataType="Text"
width="150"
minWidth="50"
maxWidth="300"
resizable>
</dike-grid-column>
</dike-grid-column>
<dike-grid-column
fieldName="gender"
headerText="Gender"
dataType="Binary"
width="110"
minWidth="50"
maxWidth="200"
resizable
draggable
groupable>
</dike-grid-column>
<dike-grid-column
fieldName="age"
headerText="Age"
dataType="Numeric"
contentAlign="center"
width="85"
minWidth="50"
maxWidth="120"
resizable
draggable
groupable>
</dike-grid-column>
</dike-grid-column>
<dike-grid-column
fieldName="hireDate"
headerText="Hire Date"
dataType="Date"
width="125"
order="4"
draggable
groupable
panel="rightPanel">
</dike-grid-column>
</dike-grid>
Last updated