Christopher Kiessling
Christopher Kiessling

Reputation: 413

Cannot read property of undefined - cdkDropListData drag-drop Angular Material

I'm using the new Angular 7 Material CDK drag-drop feature to move item from a list to another and visually everything rocks when moving those but when changing item through lists I'm getting an error saying can't get a property (the list array) from undefined, even if I'm using the "item?.array" thing

in constructor:

this.userService.getUserById('some-user-id').subscribe(user => {
  this.user1 = user;
  console.log(user1.route.routePoints); // I see the array in log
});

this.userService.getUserById('some-other-user-id').subscribe(user => {
  this.user2 = user;
  console.log(user2.route.routePoints); // I see the array in log
});

Here I'm getting the error "Cannot read property 'routePoints' of undefined" when dragging item from a list to another

<div cdkDropList #routeA="cdkDropList" cdkDropListOrientation="horizontal" 
[cdkDropListData]="user1?.route?.routePoints"
class="list" (cdkDropListDropped)="drop($event, false, user1)" 
[cdkDropListConnectedTo]="[queue, routeB]">

Here's the drag code:

drop(event: CdkDragDrop<RoutePoint[]>, fromQueue: boolean = false, user: User) {
  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);
  }
  this.userService.updateUser(user);
}

Upvotes: 6

Views: 10350

Answers (3)

Khuram Niaz
Khuram Niaz

Reputation: 919

I was getting this error cause my cdkDropListData element was not immediate parent of cdkdrag element, there was tab element in between causing issue. its ng version 7.x

Upvotes: 0

Elazar Zadiki
Elazar Zadiki

Reputation: 1137

as marcinolawski @ https://github.com/angular/components/issues/15948 mentioned, the reason is:

The problem is that _DragRef.initialContainer == undefined. This is because _DragRef.initializeDragSequence() is called earlier than _DragRef.withDropContainer(). _initializeDragSequence() initializes the _initialContainer based on _dropContainer, _dropContainer is initialized by _withDropContainer() but because _initializeDragSequence() is called earlier than _withDropContainer() _initialContainer is set to undefined. More info: https://github.com/angular/components/blob/master/src/cdk/drag-drop/drag-ref.ts

an ugly but working workaround for that is to trigger change detection on AfterViewChecked as follows (by lukaszgodula @ the same github above):

ngAfterViewChecked() {
   this.cdRef.detectChanges();
}

and of course inject ChangeDetectorRef to the component:

constructor(
   private cdRef: ChangeDetectorRef
}

Upvotes: 6

Sachila Ranawaka
Sachila Ranawaka

Reputation: 41407

Make sure to initialize the user1 array first

user: yourType = {};

this.userService.getUserById('some-user-id').subscribe(user => {
  this.user1 = user;
  console.log(user1.route.routePoints); // I see the array in log
}); 

Upvotes: 1

Related Questions