类型 'Event' 缺少类型 'CdkDragDrop<string [], string[]>' 的以下属性

Type 'Event' is missing the following properties from type 'CdkDragDrop<string [], string[]>'

我正在查看 stackblitz 上的 reorderable columns example

特别是我看到 html

<table mat-table
       [dataSource]="dataSource" 
       cdkDropList
       cdkDropListOrientation="horizontal"
       (cdkDropListDropped)="drop($event)">

我已经在 MytableComponent 中定义了 drop

export class MytableComponent implements AfterViewInit {
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  @ViewChild(MatTable) table!: MatTable<MytableItem>;
  dataSource: MytableDataSource;

  /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
  displayedColumns = ['id', 'name', 'dateOfBirth'];

  drop(event: CdkDragDrop<string[]>) {
    moveItemInArray(this.displayedColumns, event.previousIndex, event.currentIndex);
  }

  constructor() {
    this.dataSource = new MytableDataSource();
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
    this.table.dataSource = this.dataSource;
  }
}

构建失败并出现错误

Error: src/app/mytable/mytable.component.html:5:35 - error TS2345: Argument of type 'Event' is not assignable to parameter of type 'CdkDragDrop<string[], string[]>'.
  Type 'Event' is missing the following properties from type 'CdkDragDrop<string[], string[]>': previousIndex, currentIndex, item, container, and
3 more.

可能我在项目的初始设置中设置了比示例更严格的类型检查。

搜索后我看到了

  drop(event: Event)  {
      if (isDragDrop(event)) {
        moveItemInArray(this.displayedColumns, event.previousIndex, event.currentIndex);
      }
    }

编译成功,当我声明一个

function isDragDrop(object: any): object is CdkDragDrop<string[]> {
  return 'previousIndex' in object;
}

当然我必须在 app.module.ts 中导入 DragDropModule 现在我可以重新排列列

顺便说一句,也可以使用方便的助手从本地存储加载和保存列的顺序,例如 - 使用 @Input() ID: string | undefined; - 在 mytable.component.ts 中我还添加了:

  onSaveOrder() {
    if (!this.ID) {
      console.log('my-table ID not set!');
      return;
    }
    localStorage.setItem('my-table-cols-' + this.ID, this.displayedColumns.join(','));
    console.log(`table ID ${ this.ID } columns order saved ${ this.displayedColumns }`);
  }
  onLoadOrder() {
    if (!this.ID) {
      console.log('my-table ID not set!');
      return;
    }
    const saved = localStorage.getItem('my-table-cols-' + this.ID);
    if (saved) {
      this.displayedColumns = saved.split(',');  
      console.log(`table ID ${ this.ID } columns order loaded ${saved}`);
    } else {
      console.log(`table ID ${ this.ID } nothing was saved`);
    }
  }

app.component.html

中的用法
  <h3>My Table Rowss</h3>
  <app-mytable ID="MyTable1"></app-mytable>

只需将“@angular/cdk/drag-drop”中的 DragDropModule 导入组件的模块即可解决问题。

旁白: 我也遵循相同的 example on the Angular Material site 并启用了严格的类型检查。起初它看起来像是一个严格的类型检查问题,但它只是编译器在您忘记导入模块时产生的令人分心的错误消息的另一个示例。我还没有亲眼目睹过严格的类型检查导致组件崩溃。

要使拖放工作完美无缺需要满足的条件如下:

  1. 在 app.module.ts 文件中,应按如下所述导入 DragDrop 模块:

    import {DragDropModule} from '@angular/cdk/drag-drop';
    imports: [ 
    DragDropModule
    ],
    
  2. 在 Compoenent.html 中将以下属性添加到 div 或您要实现拖放的任何选择器:

    <div cdkDropList (cdkDropListDropped)="drop($event)">
               <mat-card
                 cdkDrag
                 *ngFor="let element of array" //array is the one that is 
                        given as input to the moveItemInArray() in drop()
               >
                 <div>
                     {{ element  }}
                 </div>
               </mat-card>
             </div>
    
  3. 在Component.ts文件中要实现拖放的代码如下:

     import { CdkDrag, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
    
     drop(event: CdkDragDrop<any[]>) {
        moveItemInArray(this.array, event.previousIndex, event.currentIndex);
     }
    

    其中,'this.array'是在HTML文件中拖放遍历的数组, 'moveItemInArray()' 根据拖放索引重新排列数组元素 放置在活动收到的位置。

这将解决实施拖放时出现的所有错误。