Skip to content

Commit

Permalink
feat(cdk/drag-drop): expose native event objects in custom events (#1…
Browse files Browse the repository at this point in the history
…7077)

Exposes the native `MouseEvent` and `TouchEvent` objects in the various drag&drop events since they can contain useful information like which keys were pressed while dragging.

Fixes #17032.
  • Loading branch information
crisbeto authored Feb 24, 2022
1 parent 469b790 commit ca6b9fa
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 38 deletions.
33 changes: 32 additions & 1 deletion src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,10 @@ describe('CdkDrag', () => {

// Assert the event like this, rather than `toHaveBeenCalledWith`, because Jasmine will
// go into an infinite loop trying to stringify the event, if the test fails.
expect(event).toEqual({source: fixture.componentInstance.dragInstance});
expect(event).toEqual({
source: fixture.componentInstance.dragInstance,
event: jasmine.anything(),
});
}));

it('should dispatch an event when the user has stopped dragging', fakeAsync(() => {
Expand All @@ -440,6 +443,7 @@ describe('CdkDrag', () => {
source: fixture.componentInstance.dragInstance,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand All @@ -454,6 +458,7 @@ describe('CdkDrag', () => {
source: jasmine.anything(),
distance: {x: 25, y: 30},
dropPoint: {x: 25, y: 30},
event: jasmine.anything(),
});

dragElementViaMouse(fixture, fixture.componentInstance.dragElement.nativeElement, 40, 50);
Expand All @@ -463,6 +468,7 @@ describe('CdkDrag', () => {
source: jasmine.anything(),
distance: {x: 40, y: 50},
dropPoint: {x: 40, y: 50},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -1821,6 +1827,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -1995,6 +2002,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -2071,6 +2079,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -2127,6 +2136,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -2177,6 +2187,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -2225,6 +2236,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: jasmine.any(Boolean),
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -2277,6 +2289,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: jasmine.any(Boolean),
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -2326,6 +2339,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: jasmine.any(Boolean),
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

scrollTo(0, 0);
Expand Down Expand Up @@ -4097,6 +4111,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())).toEqual([
Expand Down Expand Up @@ -4581,6 +4596,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -4827,6 +4843,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: jasmine.any(Boolean),
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -4955,6 +4972,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5070,6 +5088,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5101,6 +5120,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5132,6 +5152,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5277,6 +5298,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5420,6 +5442,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5448,6 +5471,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5481,6 +5505,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5527,6 +5552,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

expect(dropContainers[0].contains(item.element.nativeElement))
Expand Down Expand Up @@ -5633,6 +5659,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -5822,6 +5849,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: false,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
}),
);
}),
Expand Down Expand Up @@ -6198,6 +6226,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});

cleanup();
Expand Down Expand Up @@ -6244,6 +6273,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down Expand Up @@ -6282,6 +6312,7 @@ describe('CdkDrag', () => {
isPointerOverContainer: true,
distance: {x: jasmine.any(Number), y: jasmine.any(Number)},
dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)},
event: jasmine.anything(),
});
}));

Expand Down
42 changes: 22 additions & 20 deletions src/cdk/drag-drop/directives/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,55 +442,57 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {

/** Handles the events from the underlying `DragRef`. */
private _handleEvents(ref: DragRef<CdkDrag<T>>) {
ref.started.subscribe(() => {
this.started.emit({source: this});
ref.started.subscribe(startEvent => {
this.started.emit({source: this, event: startEvent.event});

// Since all of these events run outside of change detection,
// we need to ensure that everything is marked correctly.
this._changeDetectorRef.markForCheck();
});

ref.released.subscribe(() => {
this.released.emit({source: this});
ref.released.subscribe(releaseEvent => {
this.released.emit({source: this, event: releaseEvent.event});
});

ref.ended.subscribe(event => {
ref.ended.subscribe(endEvent => {
this.ended.emit({
source: this,
distance: event.distance,
dropPoint: event.dropPoint,
distance: endEvent.distance,
dropPoint: endEvent.dropPoint,
event: endEvent.event,
});

// Since all of these events run outside of change detection,
// we need to ensure that everything is marked correctly.
this._changeDetectorRef.markForCheck();
});

ref.entered.subscribe(event => {
ref.entered.subscribe(enterEvent => {
this.entered.emit({
container: event.container.data,
container: enterEvent.container.data,
item: this,
currentIndex: event.currentIndex,
currentIndex: enterEvent.currentIndex,
});
});

ref.exited.subscribe(event => {
ref.exited.subscribe(exitEvent => {
this.exited.emit({
container: event.container.data,
container: exitEvent.container.data,
item: this,
});
});

ref.dropped.subscribe(event => {
ref.dropped.subscribe(dropEvent => {
this.dropped.emit({
previousIndex: event.previousIndex,
currentIndex: event.currentIndex,
previousContainer: event.previousContainer.data,
container: event.container.data,
isPointerOverContainer: event.isPointerOverContainer,
previousIndex: dropEvent.previousIndex,
currentIndex: dropEvent.currentIndex,
previousContainer: dropEvent.previousContainer.data,
container: dropEvent.container.data,
isPointerOverContainer: dropEvent.isPointerOverContainer,
item: this,
distance: event.distance,
dropPoint: event.dropPoint,
distance: dropEvent.distance,
dropPoint: dropEvent.dropPoint,
event: dropEvent.event,
});
});
}
Expand Down
19 changes: 10 additions & 9 deletions src/cdk/drag-drop/directives/drop-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,16 +357,17 @@ export class CdkDropList<T = any> implements OnDestroy {
});
});

ref.dropped.subscribe(event => {
ref.dropped.subscribe(dropEvent => {
this.dropped.emit({
previousIndex: event.previousIndex,
currentIndex: event.currentIndex,
previousContainer: event.previousContainer.data,
container: event.container.data,
item: event.item.data,
isPointerOverContainer: event.isPointerOverContainer,
distance: event.distance,
dropPoint: event.dropPoint,
previousIndex: dropEvent.previousIndex,
currentIndex: dropEvent.currentIndex,
previousContainer: dropEvent.previousContainer.data,
container: dropEvent.container.data,
item: dropEvent.item.data,
isPointerOverContainer: dropEvent.isPointerOverContainer,
distance: dropEvent.distance,
dropPoint: dropEvent.dropPoint,
event: dropEvent.event,
});

// Mark for check since all of these events run outside of change
Expand Down
8 changes: 8 additions & 0 deletions src/cdk/drag-drop/drag-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import {CdkDropList} from './directives/drop-list';
export interface CdkDragStart<T = any> {
/** Draggable that emitted the event. */
source: CdkDrag<T>;
/** Native event that started the drag sequence. */
event: MouseEvent | TouchEvent;
}

/** Event emitted when the user releases an item, before any animations have started. */
export interface CdkDragRelease<T = any> {
/** Draggable that emitted the event. */
source: CdkDrag<T>;
/** Native event that caused the release event. */
event: MouseEvent | TouchEvent;
}

/** Event emitted when the user stops dragging a draggable. */
Expand All @@ -29,6 +33,8 @@ export interface CdkDragEnd<T = any> {
distance: {x: number; y: number};
/** Position where the pointer was when the item was dropped */
dropPoint: {x: number; y: number};
/** Native event that caused the dragging to stop. */
event: MouseEvent | TouchEvent;
}

/** Event emitted when the user moves an item into a new drop container. */
Expand Down Expand Up @@ -70,6 +76,8 @@ export interface CdkDragDrop<T, O = T, I = any> {
distance: {x: number; y: number};
/** Position where the pointer was when the item was dropped */
dropPoint: {x: number; y: number};
/** Native event that caused the drop event. */
event: MouseEvent | TouchEvent;
}

/** Event emitted as the user is dragging a draggable item. */
Expand Down
Loading

0 comments on commit ca6b9fa

Please sign in to comment.