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?
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:
cdkDropList
to mat-table
(cdkDropListDropped)="onListDrop($event)"
to mat-table
cdkDrag
to mat-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.
Found example https://stackblitz.com/edit/angular-igmugp
Looks the missing part is
this.table.renderRows();
I was using MatTableDataSource
for my dataSource so my solution was this:
Importing DragDropModule
in component.module.ts
Importing CdkDragDrop
in the component
Adding @ViewChild('table') table: MatTable<any>;
to the component.ts
.
In the HTML add:
<table mat-table #table [dataSource]="dataSource" class="mat-elevation-z8"
cdkDropList
[cdkDropListData]="dataSource"
(cdkDropListDropped)="drop($event)">
At the *matRowDef
you need to add this :
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
cdkDrag
[cdkDragData]=row>
</tr>
Then in the component.ts
I 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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With