使用角材料的拖放重新排列垫表行
Posted
技术标签:
【中文标题】使用角材料的拖放重新排列垫表行【英文标题】:Reorder mat-table rows with angular material's drag-and-drop 【发布时间】:2019-04-21 23:30:03 【问题描述】:Angular 7 带来了强大的 DragDropModule
:https://material.angular.io/cdk/drag-drop/examples
文档涉及重新排列列表中的项目或在多个列表之间转移项目。但是,它没有谈论表格。
我想知道是否有一种舒适的方法可以使用 angular material 的拖放系统来重新排序 mat-table 或 cdk-table 中的行。
(您可以将cdkDropList
添加到mat-table
,这使机制工作,但没有所有花哨的动画和默认的拖动占位符。)
是否存在类似于通过拖放对表格行进行排序的易于实现的默认设置?
【问题讨论】:
您描述了该机制正在工作。对我来说,使用实际的角度 7.1 不起作用。当我将 cdkDropList 添加到 mat-table 时,我总是收到 Uncaught TypeError: Cannot read property 'clientRect' of undefined. 【参考方案1】:样式由 CSS 完成(查看示例页面上的 CSS 选项卡)。我对其进行了调整以使用 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);
我把它放在我的主 style.scss 文件中。
对于想知道如何在 mat-table 上实现拖放的任何人,您需要:
-
将
cdkDropList
添加到mat-table
将(cdkDropListDropped)="onListDrop($event)"
添加到mat-table
将cdkDrag
添加到mat-row
onListDrop
看起来像:
onListDrop(event: CdkDragDrop<string[]>)
// Swap the elements around
moveItemInArray(this.myArray, event.previousIndex, event.currentIndex);
moveItemInArray
是一个 Angular Material 函数。你可以导入它。
【讨论】:
除此之外,别忘了将DragDropModule
添加到您的 NgModule 中,如提到的 here
目前有一个问题,event.previousIndex
只能在第一次工作。解决方法是在mat-row
上使用[cdkDragData]=row
和previousIndex = this.myDataSource.findIndex(row => row === event.item.data)
我做到了这一点,但我无法添加拖动手柄。有没有人设法使这项工作?谢谢!
使用链接中 github 问题中的 cdkrootelement 建议,我能够在拖动手柄方面取得相当大的进展。然而,在桌子上触摸滚动是行不通的。当您将项目拖动到屏幕边缘时,自动滚动也不会。
@EthanMelamed 你能展示一下你是如何用 cdkrootelement 解决它的吗?我找不到你提到的问题。【参考方案2】:
找到例子https://stackblitz.com/edit/angular-igmugp
看起来缺少的部分是
this.table.renderRows();
【讨论】:
有什么方法可以得到 currentIndex 吗?列克:const prevIndex = this.dataSource.findIndex((d) => d === event.item.data); 这个样本就像一个魅力!请注意表格组件底部的cdkDrag [cdkDragData]="row"
定义......它实际上使行可拖动【参考方案3】:
我使用MatTableDataSource
作为我的数据源,所以我的解决方案是这样的:
在component.module.ts
中导入DragDropModule
在组件
中导入CdkDragDrop
将@ViewChild('table') table: MatTable<any>;
添加到component.ts
。
在 html 中添加:
<table mat-table #table [dataSource]="dataSource" class="mat-elevation-z8"
cdkDropList
[cdkDropListData]="dataSource"
(cdkDropListDropped)="drop($event)">
在*matRowDef
你需要添加这个:
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
cdkDrag
[cdkDragData]=row>
</tr>
然后在component.ts
我做了drop事件:
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();
【讨论】:
【参考方案4】:我在 stackblitz 上找到了一个很好的例子:https://stackblitz.com/edit/table-drag-n-drop
为了不破坏拖放预览的用户界面,请使用标签
<mat-table>...</mat-table>
<mat-header-cell>...</mat-header-cell>
<mat-cell>...</mat-cell>
<mat-header-row>...</mat-header-row>
<mat-row>...</mat-row>
而不是
<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>
结合https://***.com/a/53630171/12331146中提到的css,对我来说是完美的解决方案。
【讨论】:
我同意!使用如果您仍在使用table
而不是mat-table
来呈现表格。您可以考虑手动设置表格上每个td
列的宽度。
在https://trungk18.com/experience/angular-cdk-drag-drop-list-table/上查看完整的解释和stackblitz
.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>
这是最终结果
【讨论】:
以上是关于使用角材料的拖放重新排列垫表行的主要内容,如果未能解决你的问题,请参考以下文章