fix(drag-drop): unable to drag last item back into initial container (#12261)

This commit is contained in:
Kristiyan Kostadinov
2018-07-23 18:10:41 +02:00
committed by Joey Perrott
parent 0291ec4758
commit fa83805af2
3 changed files with 68 additions and 15 deletions
+60 -12
View File
@@ -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: `
<cdk-drop
#todoZone
style="display: block; width: 100px; background: pink;"
[data]="todo"
[connectedTo]="[doneZone]"
(dropped)="droppedSpy($event)">
<div
*ngFor="let item of todo"
cdkDrag
style="width: 100%; height: ${ITEM_HEIGHT}px; background: red;">{{item}}</div>
<div *ngFor="let item of todo" cdkDrag>{{item}}</div>
</cdk-drop>
<cdk-drop
#doneZone
style="display: block; width: 100px; background: purple;"
[data]="done"
[connectedTo]="[todoZone]"
(dropped)="droppedSpy($event)">
<div
*ngFor="let item of done"
cdkDrag
style="width: 100%; height: ${ITEM_HEIGHT}px; background: green;">{{item}}</div>
<div *ngFor="let item of done" cdkDrag>{{item}}</div>
</cdk-drop>
`
})
+1 -1
View File
@@ -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;
+7 -2
View File
@@ -141,7 +141,9 @@ export class CdkDrop<T = any> {
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<T = any> {
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();