mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(drag-drop): add sorted event (#13887)
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.
This commit is contained in:
committed by
vivian-hu
parent
df5d18f283
commit
26c73e0435
@@ -71,3 +71,15 @@ export interface CdkDragMove<T = any> {
|
||||
*/
|
||||
delta: {x: -1 | 0 | 1, y: -1 | 0 | 1};
|
||||
}
|
||||
|
||||
/** Event emitted when the user swaps the position of two drag items. */
|
||||
export interface CdkDragSortEvent<T = any, I = T> {
|
||||
/** 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<T>;
|
||||
/** Item that is being sorted. */
|
||||
item: CdkDrag<I>;
|
||||
}
|
||||
|
||||
@@ -698,6 +698,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();
|
||||
@@ -2192,6 +2222,7 @@ const DROP_ZONE_FIXTURE_TEMPLATE = `
|
||||
style="width: 100px; background: pink;"
|
||||
[id]="dropZoneId"
|
||||
[cdkDropListData]="items"
|
||||
(cdkDropListSorted)="sortedSpy($event)"
|
||||
(cdkDropListDropped)="droppedSpy($event)">
|
||||
<div
|
||||
*ngFor="let item of items"
|
||||
@@ -2214,6 +2245,7 @@ class DraggableInDropZone {
|
||||
{value: 'Three', height: ITEM_HEIGHT, margin: 0}
|
||||
];
|
||||
dropZoneId = 'items';
|
||||
sortedSpy = jasmine.createSpy('sorted spy');
|
||||
droppedSpy = jasmine.createSpy('dropped spy').and.callFake((event: CdkDragDrop<string[]>) => {
|
||||
moveItemInArray(this.items, event.previousIndex, event.currentIndex);
|
||||
});
|
||||
|
||||
@@ -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';
|
||||
import {CdkDropListGroup} from './drop-list-group';
|
||||
@@ -140,6 +140,10 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
|
||||
@Output('cdkDropListExited')
|
||||
exited: EventEmitter<CdkDragExit<T>> = new EventEmitter<CdkDragExit<T>>();
|
||||
|
||||
/** Emits as the user is swapping items while actively dragging. */
|
||||
@Output('cdkDropListSorted')
|
||||
sorted: EventEmitter<CdkDragSortEvent<T>> = new EventEmitter<CdkDragSortEvent<T>>();
|
||||
|
||||
constructor(
|
||||
public element: ElementRef<HTMLElement>,
|
||||
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDropList<T>>,
|
||||
@@ -321,6 +325,13 @@ export class CdkDropList<T = any> 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) {
|
||||
|
||||
Reference in New Issue
Block a user