angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.36k stars 6.74k forks source link

Angular cdkDrag of Material table rows not working with router-outlet #15948

Closed wzheng2310 closed 4 years ago

wzheng2310 commented 5 years ago

What is the expected behavior?

When using CDK Drag & Drop with Material table rows, if the table is loaded via router-outlet, it should be able to drag & drop the rows.

What is the current behavior?

Drag & drop will fail with the following error:

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:265) at SafeSubscriber.next (Subscriber.ts:207) at Subscriber._next (Subscriber.ts:139) at Subscriber.next (Subscriber.ts:99) at Subject.next (Subject.ts:70) at HTMLDocument.handler (drag-drop-registry.ts:127) at ZoneDelegate.invokeTask (zone.js:423) at Zone.runTask (zone.js:195)

What are the steps to reproduce?

I create a stackblitz project (https://stackblitz.com/edit/angular-cdkdrag-table-row) that can reproduce the problem. Please open the debug console and you will see the following error message as soon as you try to drag a row

Take a look at app.component.html and see my comment in there.

Credit to https://stackblitz.com/edit/angular-igmugp, I followed and copied/pasted the mat-table and drag/drop code from it to create my project for the repro.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

It happens on Chrome (version 73.0.3683.86) in Ubuntu 18.04, It also happens on Windows 10 Edge For Angular/Material versions, you can find out from the stackblitz project.

Is there anything else we should know?

wzheng2310 commented 5 years ago

After some debugging, I found that the difference between using router-outlet vs loading the component directly is that when loading it directly, the following piece of code will be called when the page is created and it is not called when using router-outlet. That caused the related variable not initialized hence it got the undefined error when trying to drag/drop. However, I still don't know how to fix it yet.

` CdkDropList.prototype.ngAfterContentInit = /**

lukaszgodula commented 5 years ago

I have the same issue, anybody have maybe workaround?

I saw that one with ChangeDetecor in AfterViewChecked, but worked only without firsTime check. So it's not very optimal in my case :)

vimrookie commented 5 years ago

Any solution? I have the same issue when try drag and drop between datatables.

marcinolawski commented 5 years ago

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 Very brutal workaround: Find file drag-drop.js inside @angular directory, add the following line to the _withDropContainer() function: this._initialContainer = container; I have no idea if this code has any side effects but it solves the problem effectively.

henrikdahl8240 commented 5 years ago

Can't this problem be corrected, please? I suppose it's quite obvious, that in all non-trivial Angular apps, there will be used router-outlet(s) and drag-drop presumably just doesn't work at all as soon as you introduce a router-outlet.

lukaszgodula commented 5 years ago

Any solution? I have the same issue when try drag and drop between datatables.

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

For me only such thing worked... Ugly and not optimal but I needed this to work with any price.

mshehadeh commented 4 years ago

Any updates on this?

jeanbza commented 4 years ago

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 Very brutal workaround: Find file drag-drop.js inside @angular directory, add the following line to the _withDropContainer() function: this._initialContainer = container; I have no idea if this code has any side effects but it solves the problem effectively.

Submitted as a PR here: https://github.com/angular/components/pull/18421.

Let's see if that is the right way to fix this. :)

jeanbza commented 4 years ago

Should be fixed with https://github.com/angular/components/pull/18356 I believe.

crisbeto commented 4 years ago

Closing as fixed. If it's not sorted out after #18356 is released I'll reopen the issue.

angular-automatic-lock-bot[bot] commented 4 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.