Skip to content

Commit

Permalink
fix(drag-drop): error if item is removed while dragging (#15950)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto authored and jelbourn committed May 13, 2019
1 parent 40b335c commit a632067
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
21 changes: 21 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2515,6 +2515,27 @@ describe('CdkDrag', () => {
.toEqual(['Zero', 'One', 'Two', 'Three']);
}));

it('should not throw if an item is removed after dragging has started', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZone);
fixture.detectChanges();
const dragItems = fixture.componentInstance.dragItems;
const firstElement = dragItems.first.element.nativeElement;
const lastItemRect = dragItems.last.element.nativeElement.getBoundingClientRect();

// Start dragging.
startDraggingViaMouse(fixture, firstElement);

// Remove the last item.
fixture.componentInstance.items.pop();
fixture.detectChanges();

expect(() => {
// Move the dragged item over where the remove item would've been.
dispatchMouseEvent(document, 'mousemove', lastItemRect.left + 1, lastItemRect.top + 1);
fixture.detectChanges();
flush();
}).not.toThrow();
}));

});

Expand Down
16 changes: 13 additions & 3 deletions src/cdk/drag-drop/drop-list-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,7 @@ export class DropListRef<T = any> {
start(): void {
this.beforeStarted.next();
this._isDragging = true;
this._activeDraggables = this._draggables.slice();
this._cacheOwnPosition();
this._cacheItemPositions();
this._cacheItems();
this._siblings.forEach(sibling => sibling._startReceiving(this));
}

Expand Down Expand Up @@ -276,6 +274,11 @@ export class DropListRef<T = any> {
withItems(items: DragRef[]): this {
this._draggables = items;
items.forEach(item => item._withDropContainer(this));

if (this.isDragging()) {
this._cacheItems();
}

return this;
}

Expand Down Expand Up @@ -566,6 +569,13 @@ export class DropListRef<T = any> {
});
}

/** Caches the current items in the list and their positions. */
private _cacheItems(): void {
this._activeDraggables = this._draggables.slice();
this._cacheItemPositions();
this._cacheOwnPosition();
}

/**
* Checks whether the user's pointer is positioned over the container.
* @param x Pointer position along the X axis.
Expand Down

0 comments on commit a632067

Please sign in to comment.