diff --git a/src/cdk-experimental/drag-drop/drag.spec.ts b/src/cdk-experimental/drag-drop/drag.spec.ts index c1982e1d915b..1f160d3c4a51 100644 --- a/src/cdk-experimental/drag-drop/drag.spec.ts +++ b/src/cdk-experimental/drag-drop/drag.spec.ts @@ -657,7 +657,8 @@ describe('CdkDrag', () => { const initialRect = item.element.nativeElement.getBoundingClientRect(); const targetRect = groups[1][2].element.nativeElement.getBoundingClientRect(); - expect(dropZones[0].contains(item.element.nativeElement)).toBe(true); + expect(dropZones[0].contains(item.element.nativeElement)) + .toBe(true, 'Expected placeholder to be inside the first container.'); dispatchMouseEvent(item.element.nativeElement, 'mousedown'); fixture.detectChanges(); @@ -675,7 +676,7 @@ describe('CdkDrag', () => { fixture.detectChanges(); expect(dropZones[0].contains(placeholder)) - .toBe(true, 'Expected placeholder to be inside first container.'); + .toBe(true, 'Expected placeholder to be back inside first container.'); dispatchMouseEvent(document, 'mouseup'); fixture.detectChanges(); @@ -746,6 +747,46 @@ describe('CdkDrag', () => { assertDownwardSorting(fixture, Array.from(dropZones[1].querySelectorAll('.cdk-drag'))); })); + it('should be able to return the last item inside its initial container', fakeAsync(() => { + const fixture = createComponent(ConnectedDropZones); + + // Make sure there's only one item in the first list. + fixture.componentInstance.todo = ['things']; + fixture.detectChanges(); + + const groups = fixture.componentInstance.groupedDragItems; + const dropZones = fixture.componentInstance.dropInstances.map(d => d.element.nativeElement); + const item = groups[0][0]; + const initialRect = item.element.nativeElement.getBoundingClientRect(); + const targetRect = groups[1][0].element.nativeElement.getBoundingClientRect(); + + expect(dropZones[0].contains(item.element.nativeElement)) + .toBe(true, 'Expected placeholder to be inside the first container.'); + dispatchMouseEvent(item.element.nativeElement, 'mousedown'); + fixture.detectChanges(); + + const placeholder = dropZones[0].querySelector('.cdk-drag-placeholder')!; + + expect(placeholder).toBeTruthy(); + + dispatchMouseEvent(document, 'mousemove', targetRect.left + 1, targetRect.top + 1); + fixture.detectChanges(); + + expect(dropZones[1].contains(placeholder)) + .toBe(true, 'Expected placeholder to be inside second container.'); + + dispatchMouseEvent(document, 'mousemove', initialRect.left + 1, initialRect.top + 1); + fixture.detectChanges(); + + expect(dropZones[0].contains(placeholder)) + .toBe(true, 'Expected placeholder to be back inside first container.'); + + dispatchMouseEvent(document, 'mouseup'); + fixture.detectChanges(); + + expect(fixture.componentInstance.droppedSpy).not.toHaveBeenCalled(); + })); + }); }); @@ -916,29 +957,36 @@ export class DraggableInDropZoneWithCustomPlaceholder { @Component({ + encapsulation: ViewEncapsulation.None, + styles: [` + .cdk-drop { + display: block; + width: 100px; + min-height: ${ITEM_HEIGHT}px; + background: hotpink; + } + + .cdk-drag { + display: block; + height: ${ITEM_HEIGHT}px; + background: red; + } + `], template: ` -
{{item}}
+
{{item}}
-
{{item}}
+
{{item}}
` }) diff --git a/src/cdk-experimental/drag-drop/drag.ts b/src/cdk-experimental/drag-drop/drag.ts index 6093f2ffe387..ab49fb78db67 100644 --- a/src/cdk-experimental/drag-drop/drag.ts +++ b/src/cdk-experimental/drag-drop/drag.ts @@ -82,7 +82,7 @@ export class CdkDrag implements AfterContentInit, OnDestroy { private _activeTransform: Point = {x: 0, y: 0}; /** Whether the element is being dragged. */ - private _isDragging = false; + _isDragging = false; /** Whether the element has moved since the user started dragging it. */ private _hasMoved = false; diff --git a/src/cdk-experimental/drag-drop/drop.ts b/src/cdk-experimental/drag-drop/drop.ts index 9d50b832d782..b38d50ea958b 100644 --- a/src/cdk-experimental/drag-drop/drop.ts +++ b/src/cdk-experimental/drag-drop/drop.ts @@ -141,7 +141,9 @@ export class CdkDrop { const siblings = this._positionCache.items; const newPosition = siblings.find(({drag, clientRect}) => { if (drag === item) { - return false; + // If there's only one left item in the container, it must be + // the dragged item itself so we use it as a reference. + return siblings.length < 2; } return this.orientation === 'horizontal' ? @@ -153,7 +155,10 @@ export class CdkDrop { return; } - const element = newPosition ? newPosition.drag.element.nativeElement : null; + // Don't take the element of a dragged item as a reference, + // because it has been moved down to the end of the body. + const element = (newPosition && !newPosition.drag._isDragging) ? + newPosition.drag.element.nativeElement : null; const next = element ? element!.nextSibling : null; const parent = element ? element.parentElement! : this.element.nativeElement; const placeholder = item.getPlaceholderElement();