Skip to content

Commit f2f78a0

Browse files
authored
fix(drag-drop): error when dragging items inside transplanted… (#18356)
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.
1 parent 2497e50 commit f2f78a0

File tree

1 file changed

+11
-0
lines changed
  • src/cdk/drag-drop/directives

1 file changed

+11
-0
lines changed

src/cdk/drag-drop/directives/drag.ts

+11
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
206206
this._assignDefaults(config);
207207
}
208208

209+
// Note that usually the container is assigned when the drop list is picks up the item, but in
210+
// some cases (mainly transplanted views with OnPush, see #18341) we may end up in a situation
211+
// where there are no items on the first change detection pass, but the items get picked up as
212+
// soon as the user triggers another pass by dragging. This is a problem, because the item would
213+
// have to switch from standalone mode to drag mode in the middle of the dragging sequence which
214+
// is too late since the two modes save different kinds of information. We work around it by
215+
// assigning the drop container both from here and the list.
216+
if (dropContainer) {
217+
this._dragRef._withDropContainer(dropContainer._dropListRef);
218+
}
219+
209220
this._syncInputs(this._dragRef);
210221
this._handleEvents(this._dragRef);
211222
}

0 commit comments

Comments
 (0)