【问题标题】:Reorder mat-table rows with angular material's drag-and-drop使用角材料的拖放重新排列垫表行
【发布时间】:2019-04-21 23:30:03
【问题描述】:

Angular 7 带来了强大的 DragDropModulehttps://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.

标签: angular drag-and-drop angular-material mat-table


【解决方案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 上实现拖放的任何人,您需要:

  1. cdkDropList 添加到mat-table
  2. (cdkDropListDropped)="onListDrop($event)" 添加到mat-table
  3. 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]=rowpreviousIndex = this.myDataSource.findIndex(row =&gt; 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&lt;any&gt;; 添加到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://stackoverflow.com/a/53630171/12331146中提到的css,对我来说是完美的解决方案。

    【讨论】:

    • 我同意!使用 和相关标签 + Lee Gunn 的 CSS 效果完美!
    【解决方案5】:

    如果您仍在使用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>
    

    这是最终结果

    【讨论】:

      猜你喜欢
      • 2019-11-22
      • 1970-01-01
      • 2020-11-08
      • 1970-01-01
      • 2020-04-20
      • 2023-03-23
      • 2018-08-20
      • 2020-02-12
      • 1970-01-01
      相关资源
      最近更新 更多