如何停止CdkDropList和Material表之间的这种奇怪的交互作用

时间:2019-05-16 09:21:17

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

我正在使用Material表显示一些数据,并使用CdkDropList允许在单独的组件(mat对话框)中重新排列列/切换所用的列。

问题是CdkDropList和Material表以某种方式链接。每当我重新排列/切出CdkDropList中的列时,这些列就会在Material Table上实时重新排列/切出。听起来不错,但我不希望发生这种情况,是否要将列的配置保存到数据库中,以便在按钮按下时触发,而不是实时更改。

我完全不知道它是如何发生的,但希望有人看到我不知道的东西...

这是表格组件和对话框组件:

这是对话框组件:

      <div class="column-list-container" cdkDropListGroup>

        <p class="options-text">Columns in use</p>
        <div class="label-list-container">
          <div cdkDropList [cdkDropListData]="columns" cdkDropListOrientation="horizontal" class="label-list"
            (cdkDropListDropped)="drop($event)">
            <div class="label" *ngFor="let column of columns" cdkDrag>
              {{ column }}
            </div>
          </div>
        </div>

        <p class="options-text">Unused Columns</p>
        <div class="label-list-container">
          <div cdkDropList [cdkDropListData]="unusedColumns" cdkDropListOrientation="horizontal" class="label-list"
            (cdkDropListDropped)="drop($event)">
            <div class="label" *ngFor="let column of unusedColumns" cdkDrag>
              {{ column }}
            </div>
          </div>
        </div>

      </div>
  widget: Widget;
  columns: string[];
  unusedColumns: string[];

  constructor(
    public dialogRef: MatDialogRef<ConfigWidgetDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) { }

  ngOnInit() {
    this.widget = this.data.widget;
    this.columns = this.widget.options.columns;
    this.unusedColumns = this.widget.options.unusedColumns;
  }

  drop(event: CdkDragDrop<string[]>) {

    if (event.previousContainer === event.container) {
      moveItemInArray(
        event.container.data,
        event.previousIndex,
        event.currentIndex);
    } else {
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex);
    }
  }

  closeDialog(options: any): void {
    if (options) {
      this.widget.options.title = options.title;
      this.widget.options.columns = this.columns;
      this.widget.options.unusedColumns = this.unusedColumns;

      this.dialogRef.close(this.widget);
    } else {
      this.dialogRef.close();
    }
  }

现在是表组件:

  <div class="data-table">
    <!-- Material table component -->
    <table mat-table class="table" [dataSource]="dataSource" matSort aria-label="Elements">
      <!-- Generates Column Names -->
      <ng-container *ngFor="let col of displayedColumns" matColumnDef="{{ col }}">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>{{ col }}</th>
        <td class="table-cell" mat-cell *matCellDef="let row">
          {{ row[col] }}
        </td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row class="table-row" *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
  </div>

  <mat-paginator class="paginator" #paginator [length]="dataSource.data.length" [pageIndex]="0" [pageSize]="5"
    [pageSizeOptions]="[5, 10, 20, 50]">
  </mat-paginator>
  // material table
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  dataSource: MatTableDataSource<any> = new MatTableDataSource();
  displayedColumns: string[] = [];

  @Input() widgetInfo: any;

  constructor(
    private data: DataService,
    private stateService: StateService
  ) { }

  ngOnInit() {

    this.stateService.state.pipe(
      map(state => {
        return state.pages[this.widgetInfo.page].widgets[`${this.widgetInfo.type}${this.widgetInfo.id}`];
      }),
      filter((widget) => !!widget),
      switchMap(widget => {
        this.displayedColumns = widget.options.columns;
        return this.data.getData(widget.options.databaseTable, widget.options.preset);
      })
    ).subscribe(response => {
      this.dataSource.data = response;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
      if (response.length === 0) {
        this.noResults = true;
      }
      this.isLoadingResults = false;
    }, error => {
      console.log(error);
      this.isLoadingResults = false;
      this.errorResults = true;
    });

  }

1 个答案:

答案 0 :(得分:0)

您正在为widgets.options.columns值分配displayColumns。更改列的顺序时也可能会调用此方法。

并且表的列绑定到相同的displayColumns变量。这就是为什么它们保持同步。

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row class="table-row" *matRowDef="let row; columns: displayedColumns;"></tr>

您可以拥有一个顺序完整的单独字符串数组,并将其绑定到matRowDef和matHeaderRowDef,以保持表的列顺序不变。