'Reorder mat-table rows with angular material's drag-and-drop
Angular 7 brought the powerful DragDropModule with it: https://material.angular.io/cdk/drag-drop/examples
The documentation deals with rearranging items within lists or transferring items between several lists. However, it doesn't talk about tables.
I was wondering whether there is a comfortable way of using angular material's drag-and-drop system for reordering rows in mat-table or cdk-table.
(You can add cdkDropList to mat-table which makes the mechanism work but without all the fancy animations and default drag placeholders.)
Does something like an easy-to-implement default for sorting table rows via drag-and-drop exist?
Solution 1:[1]
The styling is done by CSS (look at the CSS tab on the example page). I tweaked it to work with mat-table:
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.cdk-drag-placeholder {
opacity: 0;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.cdk-drop-list-dragging .mat-row:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
I placed this in my main styles.scss file.
For anyone wondering how to implement drag and drop on a mat-table, you need to:
- Add
cdkDropListtomat-table - Add
(cdkDropListDropped)="onListDrop($event)"tomat-table - Add
cdkDragtomat-row
onListDrop will look something like:
onListDrop(event: CdkDragDrop<string[]>) {
// Swap the elements around
moveItemInArray(this.myArray, event.previousIndex, event.currentIndex);
}
moveItemInArray is an Angular Material function. You can import it.
Solution 2:[2]
Found example https://stackblitz.com/edit/angular-igmugp
Looks the missing part is
this.table.renderRows();
Solution 3:[3]
I was using MatTableDataSource for my dataSource so my solution was this:
Importing
DragDropModuleincomponent.module.tsImporting
CdkDragDropin the componentAdding
@ViewChild('table') table: MatTable<any>;to thecomponent.ts.In the HTML add:
<table mat-table #table [dataSource]="dataSource" class="mat-elevation-z8" cdkDropList [cdkDropListData]="dataSource" (cdkDropListDropped)="drop($event)">At the
*matRowDefyou need to add this :<tr mat-row *matRowDef="let row; columns: displayedColumns;" cdkDrag [cdkDragData]=row> </tr>Then in the
component.tsI made the drop event:drop(event: CdkDragDrop<Scene[]>) { const previousIndex = this.dataSource.data.findIndex(row => row === event.item.data); moveItemInArray(this.dataSource.data,previousIndex, event.currentIndex); this.dataSource.data = this.dataSource.data.slice(); }
Solution 4:[4]
I found a very good example on stackblitz: https://stackblitz.com/edit/table-drag-n-drop
To not break the ui of the Drag&Drop preview, use the tags
<mat-table>...</mat-table>
<mat-header-cell>...</mat-header-cell>
<mat-cell>...</mat-cell>
<mat-header-row>...</mat-header-row>
<mat-row>...</mat-row>
instead of
<table mat-table>...</table mat-table>
<th mat-header-cell>...</th mat-header-cell>
<td mat-cell>...</td mat-cell>
<tr mat-header-row>...</tr mat-header-row>
<tr mat-row>...</tr mat-row>
Combined with the css mentioned in https://stackoverflow.com/a/53630171/12331146 it is the perfect solution for me.
Solution 5:[5]
If you are still using table to render a table instead of mat-table. You can consider the approach to manually set width of each td column on your table.
See the full explanation and stackblitz on https://trungk18.com/experience/angular-cdk-drag-drop-list-table/
.col-xs {
width: 2%;
}
.col-sm {
width: 10%;
}
.col-md {
width: 20%;
}
<tbody cdkDropList (cdkDropListDropped)="onDrop($event)">
<tr *ngFor="let user of users" cdkDrag cdkDragLockAxis="y">
<th class="col-xs">
<div class="drag-handle">
<ng-container [ngTemplateOutlet]="dragHandleTmpl"> </ng-container>
</div>
</th>
<td class="col-md"></td>
<td class="col-md"></td>
<td class="col-md"></td>
<td class="col-md"></td>
</tr>
</tbody>
This is the final result

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Grebets Kostyantyn |
| Solution 3 | Cafn |
| Solution 4 | Christian Wunder |
| Solution 5 |
