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

22k Views Asked by At

I'm looking at the reorderable columns example on stackblitz.

In particular I see the html

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

I've defined the drop inside MytableComponent

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;
  }
}

The build fails with an error

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.
3

There are 3 best solutions below

0
On BEST ANSWER

Maybe I have set a stricter type checking than the example in the initial settings of the project.

After a search I see that

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

compiles successfully, when I declare a

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

Of course I have to import the DragDropModule in the app.module.ts and now I can reorder the columns

BTW, it is also possible to load and save the columns' order from local storage with convenient helpers, for example - with an @Input() ID: string | undefined; - in mytable.component.ts I've added also:

  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`);
    }
  }

Usage in app.component.html

  <h3>My Table Rowss</h3>
  <app-mytable ID="MyTable1"></app-mytable>
1
On

For Drag and drop to work flawless conditions to be met are as follows:

  1. In the app.module.ts file DragDrop module should be imported as mentioned below:

    import {DragDropModule} from '@angular/cdk/drag-drop';
    imports: [ 
    DragDropModule
    ],
    
  2. In the Compoenent.html add the below attributes to the div or any selector that you want to implement drag and drop:

    <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. In the Component.ts file in which drag and drop to be implemented below code should be implemented:

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

    where, 'this.array' is the array that is traversed for drag-drop in HTML file, 'moveItemInArray()' rearranges the array elements based on drag-drop indexes placed as received by the event.

This would solve all the errors that is being emitted while implementing drag drop.

0
On

Simply importing the DragDropModule from '@angular/cdk/drag-drop' into your component's module fixes the problem.

Aside: I also followed the same example on the Angular Material site and have strict type checking enabled. It looks like a strict type checking issue at first, but it's just another example of a distracting error message produced by the compiler when you forget to import a module. I have yet to witness strict type checking cause a component to break.