Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(drag-drop): error when dragging items inside transplanted views with OnPush change detection #18356

Conversation

crisbeto
Copy link
Member

This is a bit of an edge case, but nevertheless it's something that can happen. The way the dragging sequence works is that the drop list keeps track of its items via ContentChildren and it registers itself with them once they're picked up by the QueryList. If an item doesn't have a container when the drag sequence is started, it is considered a "standalone" drag.

This becomes a problem with transplanted views (e.g. ones created by cdk-table) that use OnPush where we could end up in a situation where the items aren't picked up during the first pass, but when the user starts dragging, we trigger change detection and the QueryList is updated, but at that point it's too late, because we've already started the dragging sequence with a different set of information.

These changes work around the issue by assigning the container manually again through the drag directive.

A couple of notes:

  • This is a second iteration of the fix. I went with this approach, because it doesn't require hacky timeouts and triggering change detection again. See the origin approach here: 22afc37
  • It's difficult to capture this in a test, because we'd have to duplicate half of the logic from CdkTable and we might still not be able to get the same change detection timing due to TestBed.

Fixes #18341.

…ith OnPush change detection

This is a bit of an edge case, but nevertheless it's something that can happen. The way the dragging sequence works is that the drop list keeps track of its items via `ContentChildren` and it registers itself with them once they're picked up by the `QueryList`. If an item doesn't have a container when the drag sequence is started, it is considered a "standalone" drag.

This becomes a problem with transplanted views (e.g. ones created by `cdk-table`) that use OnPush where we could end up in a situation where the items aren't picked up during the first pass, but when the user starts dragging, we trigger change detection and the `QueryList` is updated, but at that point it's too late, because we've already started the dragging sequence with a different set of information.

These changes work around the issue by assigning the container manually again through the drag directive.

A couple of notes:
* This is a second iteration of the fix. I went with this approach, because it doesn't require hacky timeouts and triggering change detection again. See the origin approach here: angular@22afc37
* It's difficult to capture this in a test, because we'd have to duplicate half of the logic from `CdkTable` and we might still not be able to get the same change detection timing due to `TestBed`.

Fixes angular#18341.
@crisbeto crisbeto added P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent target: patch This PR is targeted for the next patch release labels Jan 31, 2020
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jan 31, 2020
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added pr: lgtm action: merge The PR is ready for merge by the caretaker labels Feb 6, 2020
@andrewseguin andrewseguin added P2 The issue is important to a large percentage of users, with a workaround and removed P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent labels Feb 6, 2020
@jeanbza
Copy link
Contributor

jeanbza commented Feb 7, 2020

Confirmed in cl/293831687 that this fixes #15948.

@mmalerba mmalerba merged commit f2f78a0 into angular:master Feb 7, 2020
mmalerba pushed a commit that referenced this pull request Feb 19, 2020
This is a bit of an edge case, but nevertheless it's something that can happen. The way the dragging sequence works is that the drop list keeps track of its items via `ContentChildren` and it registers itself with them once they're picked up by the `QueryList`. If an item doesn't have a container when the drag sequence is started, it is considered a "standalone" drag.

This becomes a problem with transplanted views (e.g. ones created by `cdk-table`) that use OnPush where we could end up in a situation where the items aren't picked up during the first pass, but when the user starts dragging, we trigger change detection and the `QueryList` is updated, but at that point it's too late, because we've already started the dragging sequence with a different set of information.

These changes work around the issue by assigning the container manually again through the drag directive.

A couple of notes:
* This is a second iteration of the fix. I went with this approach, because it doesn't require hacky timeouts and triggering change detection again. See the origin approach here: 22afc37
* It's difficult to capture this in a test, because we'd have to duplicate half of the logic from `CdkTable` and we might still not be able to get the same change detection timing due to `TestBed`.

Fixes #18341.
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement P2 The issue is important to a large percentage of users, with a workaround target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Drag & Drop with MatTable crashes in OnPush scenarios
6 participants