1

Firstly, I've seen Type 'Event' is missing the following properties from type 'CdkDragDrop<string [], string[]>'. However, I'm already importing the DragDropModule from '@angular/cdk/drag-drop' and my problems persist.

I'm using Angular and Angular CDK to build a simple application which allows me to move items between multiple lists. I have a dynamic number of Islands. Each island has a number of parks, and each parks have a number of dinosaurs. I want to be able to move dinosaurs between different parks within the same island or to parks on other islands.

However, VS Code is showing me multiple errors from my app.component.html. It doesn't seem like Angular is recognizing 'cdkDropListData' and 'cdkDropListConnectedTo'. I'm also getting some sort of type missmatch for the event arguments.

Here's my errors:

  • Can't bind to 'cdkDropListData' since it isn't a known property of 'div'.
  • Can't bind to 'cdkDropListConnectedTo' since it isn't a known property of 'div'.
  • Argument of type 'Event' is not assignable to parameter of type 'CdkDragDrop<Dinosaur[], Dinosaur[], any>'. Type 'Event' is missing the following properties from type 'CdkDragDrop<Dinosaur[], Dinosaur[], any>': previousIndex, currentIndex, item, container, and 4 more.

In the case of the first two, this seems to be a module problem, but my DragDropModule is already imported. The type error I don't understand either. It worked fine when the type was <string[]>, but after changing to type <Dinosaur[]>, I'm getting the type missmatch problem.

I just generated the project using the Angular CLI today and have installed the npm package '@angular/cdk'. I've made no other changes.

This is my code:

app.component.html:

    <div style="border-style: solid; padding: 20px">
      <div class="container">
        <div class="row">
          <div class="col-md-4" *ngFor="let island of islands">
            <div class="drag-container">
    
              <div class="section-heading">Island: {{island.id}}</div>
              <hr>
    
    
              <div *ngFor="let park of island.parks;">
                <h5>Park: {{park.id}}</h5>
                <p>Count: {{park.dinosaurs.length}}</p>
                <p>ConnectedTo: {{park.connectedTo}}</p>
    
                <!-- cdkDropList -->
                <div cdkDropList class="item-list" id="{{park.id}}" [cdkDropListData]="park.dinosaurs"
                  [cdkDropListConnectedTo]="park.connectedTo" (cdkDropListDropped)="drop($event)">
    
                  <!-- Cdk droplist item-->
                  <div *ngFor="let dinosaur of park.dinosaurs;" cdkDrag class="item-box">
                    Dinosaur: {{dinosaur.id}}
                  </div>
    
                </div>
    
    
              </div>
    
            </div>
          </div>
        </div>
      </div>
    </div>

app.component.ts

    import { Component } from '@angular/core';

import {
  CdkDragDrop,
  moveItemInArray,
  transferArrayItem,
  CdkDrag,
} from '@angular/cdk/drag-drop';

import { Island } from './Models/islands';
import { Dinosaur } from './Models/dinosaurs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  islands: Island[] = [];

  constructor() {}

  ngOnInit() {

    // create lists of dinos 
    // todo - import from API. 

    this.islands = [
      {
        id: 1,
        parks: [
          {
            id: 1,
            dinosaurs: [
              { id: 1, name: 'Raptor', start: new Date(), end: new Date() },
              { id: 2, name: 'Raptor', start: new Date(), end: new Date() },
              { id: 3, name: 'Raptor', start: new Date(), end: new Date() },
            ],
            connectedTo: [],
          },
        ],
      },
      {
        id: 2,
        parks: [
          {
            id: 2,
            dinosaurs: [
              { id: 4, name: 'Raptor', start: new Date(), end: new Date() },
            ],
            connectedTo: [],
          },
        ],
      },
      {
        id: 3,
        parks: [
          {
            id: 3,
            dinosaurs: [
              { id: 5, name: 'Raptor', start: new Date(), end: new Date() },
            ],
            connectedTo: [],
          },
        ],
      },
      {
        id: 4,
        parks: [
          {
            id: 4,
            dinosaurs: [
              { id: 6, name: 'Raptor', start: new Date(), end: new Date() },
            ],
            connectedTo: [],
          },
        ],
      },
    ];

    // "connect" all parks to every other park 
    // so that i can move dinos between all parks 

    for (let island of this.islands) {
      for (let park of island.parks) {
        let connectedToTemp: number[] = [];

        for (let island2 of this.islands) {
          for (let park2 of island2.parks) {
            connectedToTemp.push(park2.id);
          }
        }

        park.connectedTo = connectedToTemp;
      }
    }

    console.log(this.islands);
  }

  drop(event: CdkDragDrop<Dinosaur[]>) {
    console.log(event);

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

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DragDropModule } from '@angular/cdk/drag-drop';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    DragDropModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Models/dinosaurs.ts

export interface Dinosaur{
id : number,
name : string,
start : Date;
end : Date;
}

Models/islands.ts

import { Park } from "./parks";

export interface Island{
    id : number,
    parks : Park[]
}

Models/parks.ts

import { Dinosaur } from "./dinosaurs";

export interface Park{
    connectedTo: number[];
    id : number,
    dinosaurs : Dinosaur[]
}

PS: I'm using this example as a base for my code. I don't think I'm doing anything that isn't already in that example: https://www.freakyjolly.com/angular-material-drag-and-drop-across-multi-lists-example/comment-page-1/?unapproved=7380&moderation-hash=b8259c9a206c5aeb23bc532c5126d70f#comment-7380.

user1531921
  • 1,372
  • 4
  • 18
  • 36

1 Answers1

1

I had your same problem and I found the solution on the angular cdk documentation. API reference for Angular CDK drag-drop

You need to add the dragAndDropModule to the imports list of your module:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { ProjectComponent } from './project.component';

@NgModule({
  declarations: [ProjectComponent],
  imports: [CommonModule, DragDropModule],
})
export class ProjectModule {}
Dharman
  • 30,962
  • 25
  • 85
  • 135