From ce567b8175c8a1ba312f19cccbf0a6fcfab290c8 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Wed, 31 Oct 2018 21:01:49 +0100 Subject: [PATCH] refactor(drag-drop): add sorted event Adds a new `cdkDropListSorted` event that emits the item's previous index and current index as it's being sorted in a list. Fixes #13863. --- src/cdk/drag-drop/drag-events.ts | 12 ++++++++++++ src/cdk/drag-drop/drag.spec.ts | 32 ++++++++++++++++++++++++++++++++ src/cdk/drag-drop/drop-list.ts | 13 ++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/cdk/drag-drop/drag-events.ts b/src/cdk/drag-drop/drag-events.ts index 5024bba43dce..f1e1ffb23140 100644 --- a/src/cdk/drag-drop/drag-events.ts +++ b/src/cdk/drag-drop/drag-events.ts @@ -71,3 +71,15 @@ export interface CdkDragMove { */ delta: {x: -1 | 0 | 1, y: -1 | 0 | 1}; } + +/** Event emitted when the user swaps the position of two drag items. */ +export interface CdkDragSortEvent { + /** Index from which the item was sorted previously. */ + previousIndex: number; + /** Index that the item is currently in. */ + currentIndex: number; + /** Container that the item belongs to. */ + container: CdkDropListContainer; + /** Item that is being sorted. */ + item: CdkDrag; +} diff --git a/src/cdk/drag-drop/drag.spec.ts b/src/cdk/drag-drop/drag.spec.ts index d131461ed73e..0f6f13061498 100644 --- a/src/cdk/drag-drop/drag.spec.ts +++ b/src/cdk/drag-drop/drag.spec.ts @@ -633,6 +633,36 @@ describe('CdkDrag', () => { .toEqual(['One', 'Two', 'Zero', 'Three']); })); + it('should dispatch the `sorted` event as an item is being sorted', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZone); + fixture.detectChanges(); + + const items = fixture.componentInstance.dragItems.map(item => item.element.nativeElement); + const draggedItem = items[0]; + const {top, left} = draggedItem.getBoundingClientRect(); + + startDraggingViaMouse(fixture, draggedItem, left, top); + + // Drag over each item one-by-one going downwards. + for (let i = 1; i < items.length; i++) { + const elementRect = items[i].getBoundingClientRect(); + + dispatchMouseEvent(document, 'mousemove', elementRect.left, elementRect.top + 5); + fixture.detectChanges(); + + expect(fixture.componentInstance.sortedSpy.calls.mostRecent().args[0]).toEqual({ + previousIndex: i - 1, + currentIndex: i, + item: fixture.componentInstance.dragItems.first, + container: fixture.componentInstance.dropInstance + }); + } + + 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(); @@ -2075,6 +2105,7 @@ const DROP_ZONE_FIXTURE_TEMPLATE = ` style="width: 100px; background: pink;" [id]="dropZoneId" [cdkDropListData]="items" + (cdkDropListSorted)="sortedSpy($event)" (cdkDropListDropped)="droppedSpy($event)">
) => { moveItemInArray(this.items, event.previousIndex, event.currentIndex); }); diff --git a/src/cdk/drag-drop/drop-list.ts b/src/cdk/drag-drop/drop-list.ts index 7e4add8e0f3e..f659d9b950eb 100644 --- a/src/cdk/drag-drop/drop-list.ts +++ b/src/cdk/drag-drop/drop-list.ts @@ -24,7 +24,7 @@ import { import {Directionality} from '@angular/cdk/bidi'; import {CdkDrag} from './drag'; import {DragDropRegistry} from './drag-drop-registry'; -import {CdkDragDrop, CdkDragEnter, CdkDragExit} from './drag-events'; +import {CdkDragDrop, CdkDragEnter, CdkDragExit, CdkDragSortEvent} from './drag-events'; import {moveItemInArray} from './drag-utils'; import {CDK_DROP_LIST_CONTAINER} from './drop-list-container'; @@ -139,6 +139,10 @@ export class CdkDropList implements OnInit, OnDestroy { @Output('cdkDropListExited') exited: EventEmitter> = new EventEmitter>(); + /** Emits as the user is swapping items while actively dragging. */ + @Output('cdkDropListSorted') + sorted: EventEmitter> = new EventEmitter>(); + constructor( public element: ElementRef, private _dragDropRegistry: DragDropRegistry>, @@ -311,6 +315,13 @@ export class CdkDropList implements OnInit, OnDestroy { // Shuffle the array in place. moveItemInArray(siblings, currentIndex, newIndex); + this.sorted.emit({ + previousIndex: currentIndex, + currentIndex: newIndex, + container: this, + item + }); + siblings.forEach((sibling, index) => { // Don't do anything if the position hasn't changed. if (oldOrder[index] === sibling) {