Skip to content

Commit a632067

Browse files
crisbetojelbourn
authored andcommitted
fix(drag-drop): error if item is removed while dragging (#15950)
Fixes the drop list throwing an error if an item is removed after the user started dragging, because we still have it in the position cache. Fixes #15827.
1 parent 40b335c commit a632067

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,6 +2515,27 @@ describe('CdkDrag', () => {
25152515
.toEqual(['Zero', 'One', 'Two', 'Three']);
25162516
}));
25172517

2518+
it('should not throw if an item is removed after dragging has started', fakeAsync(() => {
2519+
const fixture = createComponent(DraggableInDropZone);
2520+
fixture.detectChanges();
2521+
const dragItems = fixture.componentInstance.dragItems;
2522+
const firstElement = dragItems.first.element.nativeElement;
2523+
const lastItemRect = dragItems.last.element.nativeElement.getBoundingClientRect();
2524+
2525+
// Start dragging.
2526+
startDraggingViaMouse(fixture, firstElement);
2527+
2528+
// Remove the last item.
2529+
fixture.componentInstance.items.pop();
2530+
fixture.detectChanges();
2531+
2532+
expect(() => {
2533+
// Move the dragged item over where the remove item would've been.
2534+
dispatchMouseEvent(document, 'mousemove', lastItemRect.left + 1, lastItemRect.top + 1);
2535+
fixture.detectChanges();
2536+
flush();
2537+
}).not.toThrow();
2538+
}));
25182539

25192540
});
25202541

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ export class DropListRef<T = any> {
176176
start(): void {
177177
this.beforeStarted.next();
178178
this._isDragging = true;
179-
this._activeDraggables = this._draggables.slice();
180-
this._cacheOwnPosition();
181-
this._cacheItemPositions();
179+
this._cacheItems();
182180
this._siblings.forEach(sibling => sibling._startReceiving(this));
183181
}
184182

@@ -276,6 +274,11 @@ export class DropListRef<T = any> {
276274
withItems(items: DragRef[]): this {
277275
this._draggables = items;
278276
items.forEach(item => item._withDropContainer(this));
277+
278+
if (this.isDragging()) {
279+
this._cacheItems();
280+
}
281+
279282
return this;
280283
}
281284

@@ -566,6 +569,13 @@ export class DropListRef<T = any> {
566569
});
567570
}
568571

572+
/** Caches the current items in the list and their positions. */
573+
private _cacheItems(): void {
574+
this._activeDraggables = this._draggables.slice();
575+
this._cacheItemPositions();
576+
this._cacheOwnPosition();
577+
}
578+
569579
/**
570580
* Checks whether the user's pointer is positioned over the container.
571581
* @param x Pointer position along the X axis.

0 commit comments

Comments
 (0)