Reorder mat-table rows with angular material's drag-and-drop

后端 未结 5 1326
天涯浪人
天涯浪人 2020-12-29 08:59

Angular 7 brought the powerful DragDropModule with it: https://material.angular.io/cdk/drag-drop/examples

The documentation deals with rearranging items

相关标签:
5条回答
  • 2020-12-29 09:13

    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.

    0 讨论(0)
  • 2020-12-29 09:14

    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:

    1. Add cdkDropList to mat-table
    2. Add (cdkDropListDropped)="onListDrop($event)" to mat-table
    3. Add 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.

    0 讨论(0)
  • 2020-12-29 09:15

    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

    Angular CDK Drag/Drop List inside table (not Material Table) - Handle rows distorting width

    0 讨论(0)
  • 2020-12-29 09:17

    I was using MatTableDataSource for my dataSource so my solution was this:

    • Importing CdkDragDrop in the component and in the component.module.ts

    • 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();
      }
      
    0 讨论(0)
  • 2020-12-29 09:32

    Found example https://stackblitz.com/edit/angular-igmugp

    Looks the missing part is

    this.table.renderRows();
    
    0 讨论(0)
提交回复
热议问题