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();