Skip to content

Commit 1ac9386

Browse files
crisbetojelbourn
authored andcommitted
fix(drag-drop): don't allow user to move item into container that isn't connected to current one by passing it over an intermediate one that is (#15660)
In a setup like `Container 1 <-> Container 2 <-> Container 3` the user shouldn't be allowed to move items between containers 1 and 3, because they're not connected. This is currently possible if the user passes it through container 2 first. These changes rework the logic so that this is no longer possible. Fixes #15191.
1 parent 6c03e2f commit 1ac9386

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3193,6 +3193,63 @@ describe('CdkDrag', () => {
31933193

31943194
}));
31953195

3196+
it('should not be able to move an item into a drop container that the initial container is ' +
3197+
'not connected to by passing it over an intermediate one that is', fakeAsync(() => {
3198+
const fixture = createComponent(ConnectedDropZones);
3199+
fixture.detectChanges();
3200+
3201+
const dropInstances = fixture.componentInstance.dropInstances.toArray();
3202+
dropInstances[0].connectedTo = [dropInstances[1]];
3203+
dropInstances[1].connectedTo = [dropInstances[0], dropInstances[2]];
3204+
dropInstances[2].connectedTo = [dropInstances[1]];
3205+
fixture.detectChanges();
3206+
3207+
const groups = fixture.componentInstance.groupedDragItems;
3208+
const dropZones = dropInstances.map(d => d.element.nativeElement);
3209+
const item = groups[0][1];
3210+
const intermediateRect = dropZones[1].getBoundingClientRect();
3211+
const finalRect = dropZones[2].getBoundingClientRect();
3212+
3213+
startDraggingViaMouse(fixture, item.element.nativeElement);
3214+
3215+
const placeholder = dropZones[0].querySelector('.cdk-drag-placeholder')!;
3216+
3217+
expect(placeholder).toBeTruthy();
3218+
expect(dropZones[0].contains(placeholder))
3219+
.toBe(true, 'Expected placeholder to be inside the first container.');
3220+
3221+
dispatchMouseEvent(document, 'mousemove',
3222+
intermediateRect.left + 1, intermediateRect.top + 1);
3223+
fixture.detectChanges();
3224+
3225+
expect(dropZones[1].contains(placeholder))
3226+
.toBe(true, 'Expected placeholder to be inside second container.');
3227+
3228+
dispatchMouseEvent(document, 'mousemove', finalRect.left + 1, finalRect.top + 1);
3229+
fixture.detectChanges();
3230+
3231+
expect(dropZones[1].contains(placeholder))
3232+
.toBe(true, 'Expected placeholder to remain in the second container.');
3233+
3234+
dispatchMouseEvent(document, 'mouseup');
3235+
fixture.detectChanges();
3236+
flush();
3237+
fixture.detectChanges();
3238+
3239+
const event = fixture.componentInstance.droppedSpy.calls.mostRecent().args[0];
3240+
3241+
expect(event).toBeTruthy();
3242+
expect(event).toEqual(jasmine.objectContaining({
3243+
previousIndex: 1,
3244+
currentIndex: 1,
3245+
item: groups[0][1],
3246+
container: dropInstances[1],
3247+
previousContainer: dropInstances[0],
3248+
isPointerOverContainer: false
3249+
}));
3250+
3251+
}));
3252+
31963253
it('should return the item to its initial position, if sorting in the source container ' +
31973254
'was disabled', fakeAsync(() => {
31983255
const fixture = createComponent(ConnectedDropZones);

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,7 @@ export class DragRef<T = any> {
754754
*/
755755
private _updateActiveDropContainer({x, y}: Point) {
756756
// Drop container that draggable has been moved into.
757-
let newContainer = this._dropContainer!._getSiblingContainerFromPosition(this, x, y) ||
758-
this._initialContainer._getSiblingContainerFromPosition(this, x, y);
757+
let newContainer = this._initialContainer._getSiblingContainerFromPosition(this, x, y);
759758

760759
// If we couldn't find a new container to move the item into, and the item has left it's
761760
// initial container, check whether the it's over the initial container. This handles the

0 commit comments

Comments
 (0)