From ce8f778341f816f74fccb5d09003524ae1d36042 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 15 Sep 2021 17:27:38 +0200 Subject: [PATCH] fix(cdk/drag-drop): sorted event emitted multiple times for single-item list Fixes that the `sorted` event was being emitted when the item wasn't actually being sorted when it's inside of a list with a single item. Fixes #23575. --- src/cdk/drag-drop/directives/drag.spec.ts | 23 +++++++++++++++++++++++ src/cdk/drag-drop/drop-list-ref.ts | 7 +++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 9624ec94d7a8..ab9a1bf9431b 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -1861,6 +1861,29 @@ describe('CdkDrag', () => { flush(); })); + it('should not dispatch the `sorted` event when an item is dragged inside ' + + 'a single-item list', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZone); + fixture.componentInstance.items = [fixture.componentInstance.items[0]]; + fixture.detectChanges(); + + const draggedItem = fixture.componentInstance.dragItems.first.element.nativeElement; + const {top, left} = draggedItem.getBoundingClientRect(); + + startDraggingViaMouse(fixture, draggedItem, left, top); + + for (let i = 0; i < 5; i++) { + dispatchMouseEvent(document, 'mousemove', left, top + 1); + fixture.detectChanges(); + + expect(fixture.componentInstance.sortedSpy).not.toHaveBeenCalled(); + } + + dispatchMouseEvent(document, 'mouseup'); + fixture.detectChanges(); + flush(); + })); + it('should not move items in a vertical list if the pointer is too far away', fakeAsync(() => { const fixture = createComponent(DraggableInDropZone); fixture.detectChanges(); diff --git a/src/cdk/drag-drop/drop-list-ref.ts b/src/cdk/drag-drop/drop-list-ref.ts index 9aa46ba3fb7b..56d0a65f2f14 100644 --- a/src/cdk/drag-drop/drop-list-ref.ts +++ b/src/cdk/drag-drop/drop-list-ref.ts @@ -754,11 +754,10 @@ export class DropListRef { private _getItemIndexFromPointerPosition(item: DragRef, pointerX: number, pointerY: number, delta?: {x: number, y: number}): number { const isHorizontal = this._orientation === 'horizontal'; - const index = this._itemPositions.findIndex(({drag, clientRect}, _, array) => { + const index = this._itemPositions.findIndex(({drag, clientRect}) => { + // Skip the item itself. if (drag === item) { - // If there's only one item left in the container, it must be - // the dragged item itself so we use it as a reference. - return array.length < 2; + return false; } if (delta) {