Angular CDK drag and drop lists break when their data is re-instantiated
Asked Answered
C

1

5

I have a cdkDropListGroup with multiple tables (with the mat-table directive) that I am trying to set up drag and drop so that elements within the table can be rearranged or dragged to another table. However, when the data for the drag and drop lists is re-instantiated, the item doesn't drag and an error is logged in the console. Here is a stackblitz recreating the issue. Try to drag rows between tables or within tables a few times, the errors should appear and the drag and drop should get stuck every few attempts. How to fix this problem since in my actual code this data is coming from some http service and must be re-instantiated and the tables must be repopulated every time an item is drag and dropped to a new position?

https://stackblitz.com/edit/angular-e3ajdt

And here is the error I see.

    zone.js:192 Uncaught TypeError: Cannot read property '_getSiblingContainerFromPosition' of undefined
    at DragRef._updateActiveDropContainer (drag-ref.ts:727)
    at SafeSubscriber.DragRef._pointerMove [as _next] (drag-ref.ts:505)
    at SafeSubscriber.__tryOrUnsub (Subscriber.ts:270)
    at SafeSubscriber.next (Subscriber.ts:212)
    at Subscriber._next (Subscriber.ts:141)
    at Subscriber.next (Subscriber.ts:101)
    at Subject.next (Subject.ts:68)
    at HTMLDocument.handler (drag-drop-registry.ts:127)
    at ZoneDelegate.invokeTask (zone.js:421)
    at Zone.runTask (zone.js:188)
        DragRef._updateActiveDropContainer @ drag-ref.ts:727
        DragRef._pointerMove @ drag-ref.ts:505
        SafeSubscriber.__tryOrUnsub @ Subscriber.ts:270
        SafeSubscriber.next @ Subscriber.ts:212
        Subscriber._next @ Subscriber.ts:141
        Subscriber.next @ Subscriber.ts:101
        Subject.next @ Subject.ts:68
handler @ drag-drop-registry.ts:127
        ZoneDelegate.invokeTask @ zone.js:421
        Zone.runTask @ zone.js:188
        ZoneTask.invokeTask @ zone.js:496
        invokeTask @ zone.js:1540
        globalZoneAwareCaptureCallback @ zone.js:1598
        setTimeout (async)
        scheduleTask @ zone.js:2075
        ZoneDelegate.scheduleTask @ zone.js:407
        Zone.scheduleTask @ zone.js:232
        Zone.scheduleMacroTask @ zone.js:255
        scheduleMacroTaskWithCurrentZone @ zone.js:1114
        (anonymous) @ zone.js:2090
        proto.(anonymous function) @ zone.js:1394
        hostReportError @ hostReportError.ts:7
        SafeSubscriber.__tryOrUnsub @ Subscriber.ts:276
SafeSubscriber.next @ Subscriber.ts:212
Subscriber._next @ Subscriber.ts:141
Subscriber.next @ Subscriber.ts:101
Subject.next @ Subject.ts:68
handler @ drag-drop-registry.ts:127
ZoneDelegate.invokeTask @ zone.js:421
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCaptureCallback @ zone.js:1598
preview-ee4d58d6ef0576b4e139b.js:1 Unhandled Promise rejection: Cannot read property 'getItemIndex' of undefined ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'getItemIndex' of undefined
    at eval (drag-ref.ts:710)
    at ZoneDelegate.invoke (zone.js:388)
    at Object.onInvoke (ng_zone.ts:273)
    at ZoneDelegate.invoke (zone.js:387)
    at Zone.run (zone.js:138)
    at NgZone.run (ng_zone.ts:171)
    at DragRef._cleanupDragArtifacts (drag-ref.ts:700)
    at eval (drag-ref.ts:577)
    at ZoneDelegate.invoke (zone.js:388)
    at Zone.run (zone.js:138) TypeError: Cannot read property 'getItemIndex' of undefined
    at eval (https://angular-e3ajdt.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/cdk-drag-drop.umd.js:895:56)
    at ZoneDelegate.invoke (https://angular-e3ajdt.stackblitz.io/turbo_modules/[email protected]/dist/zone.js:388:26)
    at Object.onInvoke (https://angular-e3ajdt.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/core.umd.js:16186:37)
    at ZoneDelegate.invoke (https://angular-e3ajdt.stackblitz.io/turbo_modules/[email protected]/dist/zone.js:387:32)
    at Zone.run (https://angular-e3ajdt.stackblitz.io/turbo_modules/[email protected]/dist/zone.js:138:43)
    at NgZone.run (https://angular-e3ajdt.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/core.umd.js:16100:32)
    at DragRef._cleanupDragArtifacts (https://angular-e3ajdt.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/cdk-drag-drop.umd.js:883:22)
    at eval (https://angular-e3ajdt.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/cdk-drag-drop.umd.js:363:23)
    at ZoneDelegate.invoke (https://angular-e3ajdt.stackblitz.io/turbo_modules/[email protected]/dist/zone.js:388:26)
    at Zone.run (https://angular-e3ajdt.stackblitz.io/turbo_modules/[email protected]/dist/zone.js:138:43)
Conformance answered 4/3, 2019 at 17:16 Comment(0)
C
7

Fixed this by injecting angular's ChangeDetectorRef and calling detectChanges() every time the data is re-instantiated in the populateDataSource method.

Conformance answered 4/3, 2019 at 18:43 Comment(1)
If you look at the stackblitz table-expended-rows-example.ts line 73. Every time the data is populated changeDetectorRef.detectChanges() is called. Which happens when the data is initialized (eg if you get it from the back end or something) and every time an item is dropped stackblitz.com/edit/angular-e3ajdtConformance

© 2022 - 2024 — McMap. All rights reserved.