Skip to content

Commit

Permalink
feat(drag-drop): expose native event objects in custom events
Browse files Browse the repository at this point in the history
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 angular#17032.
  • Loading branch information
crisbeto committed Sep 13, 2019
1 parent 31d8819 commit 7b3c5bd
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 37 deletions.
37 changes: 19 additions & 18 deletions src/cdk/drag-drop/directives/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,50 +364,51 @@ 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 => {
this.ended.emit({source: this, distance: event.distance});
ref.ended.subscribe(endEvent => {
this.ended.emit({source: this, distance: endEvent.distance, 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
distance: dropEvent.distance,
event: dropEvent.event
});
});
}
Expand Down
17 changes: 9 additions & 8 deletions src/cdk/drag-drop/directives/drop-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,16 @@ export class CdkDropList<T = any> implements CdkDropListContainer, AfterContentI
});
});

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
previousIndex: dropEvent.previousIndex,
currentIndex: dropEvent.currentIndex,
previousContainer: dropEvent.previousContainer.data,
container: dropEvent.container.data,
item: dropEvent.item.data,
isPointerOverContainer: dropEvent.isPointerOverContainer,
distance: dropEvent.distance,
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 @@ -27,6 +31,8 @@ export interface CdkDragEnd<T = any> {
source: CdkDrag<T>;
/** Distance in pixels that the user has dragged since the drag sequence started. */
distance: {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 @@ -67,6 +73,8 @@ export interface CdkDragDrop<T, O = T> {
isPointerOverContainer: boolean;
/** Distance in pixels that the user has dragged since the drag sequence started. */
distance: {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
19 changes: 11 additions & 8 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,13 @@ export class DragRef<T = any> {
beforeStarted = new Subject<void>();

/** Emits when the user starts dragging the item. */
started = new Subject<{source: DragRef}>();
started = new Subject<{source: DragRef, event: MouseEvent | TouchEvent}>();

/** Emits when the user has released a drag item, before any animations have started. */
released = new Subject<{source: DragRef}>();
released = new Subject<{source: DragRef, event: MouseEvent | TouchEvent}>();

/** Emits when the user stops dragging an item in the container. */
ended = new Subject<{source: DragRef, distance: Point}>();
ended = new Subject<{source: DragRef, distance: Point, event: MouseEvent | TouchEvent}>();

/** Emits when the user has moved the item into a new container. */
entered = new Subject<{container: DropListRef, item: DragRef, currentIndex: number}>();
Expand All @@ -251,6 +251,7 @@ export class DragRef<T = any> {
previousContainer: DropListRef;
distance: Point;
isPointerOverContainer: boolean;
event: MouseEvent | TouchEvent;
}>();

/**
Expand Down Expand Up @@ -628,7 +629,7 @@ export class DragRef<T = any> {
return;
}

this.released.next({source: this});
this.released.next({source: this, event});

if (this._dropContainer) {
// Stop scrolling immediately, instead of waiting for the animation to finish.
Expand All @@ -647,7 +648,8 @@ export class DragRef<T = any> {
this._ngZone.run(() => {
this.ended.next({
source: this,
distance: this._getDragDistance(this._getPointerPositionOnPage(event))
distance: this._getDragDistance(this._getPointerPositionOnPage(event)),
event
});
});
this._cleanupCachedDimensions();
Expand All @@ -658,7 +660,7 @@ export class DragRef<T = any> {
/** Starts the dragging sequence. */
private _startDragSequence(event: MouseEvent | TouchEvent) {
// Emit the event on the item before the one on the container.
this.started.next({source: this});
this.started.next({source: this, event});

if (isTouchEvent(event)) {
this._lastTouchEventTime = Date.now();
Expand Down Expand Up @@ -783,15 +785,16 @@ export class DragRef<T = any> {
const isPointerOverContainer = container._isOverContainer(
pointerPosition.x, pointerPosition.y);

this.ended.next({source: this, distance});
this.ended.next({source: this, distance, event});
this.dropped.next({
item: this,
currentIndex,
previousIndex: this._initialContainer.getItemIndex(this),
container: container,
previousContainer: this._initialContainer,
isPointerOverContainer,
distance
distance,
event
});
container.drop(this, currentIndex, this._initialContainer, isPointerOverContainer, distance);
this._dropContainer = this._initialContainer;
Expand Down
8 changes: 6 additions & 2 deletions src/cdk/drag-drop/drop-list-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export class DropListRef<T = any> {
previousContainer: DropListRef,
isPointerOverContainer: boolean,
distance: Point;
event: MouseEvent | TouchEvent;
}>();

/** Emits as the user is swapping items while actively dragging. */
Expand Down Expand Up @@ -335,9 +336,11 @@ export class DropListRef<T = any> {
* container when the item was dropped.
* @param distance Distance the user has dragged since the start of the dragging sequence.
* @breaking-change 9.0.0 `distance` parameter to become required.
* 10.0.0 `event` parameter to become required.
*/
drop(item: DragRef, currentIndex: number, previousContainer: DropListRef,
isPointerOverContainer: boolean, distance: Point = {x: 0, y: 0}): void {
isPointerOverContainer: boolean, distance: Point = {x: 0, y: 0},
event: MouseEvent | TouchEvent = {} as any): void {
this._reset();
this.dropped.next({
item,
Expand All @@ -346,7 +349,8 @@ export class DropListRef<T = any> {
container: this,
previousContainer,
isPointerOverContainer,
distance
distance,
event
});
}

Expand Down
11 changes: 10 additions & 1 deletion tools/public_api_guard/cdk/drag-drop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface CdkDragDrop<T, O = T> {
x: number;
y: number;
};
event: MouseEvent | TouchEvent;
isPointerOverContainer: boolean;
item: CdkDrag;
previousContainer: CdkDropList<O>;
Expand All @@ -68,6 +69,7 @@ export interface CdkDragEnd<T = any> {
x: number;
y: number;
};
event: MouseEvent | TouchEvent;
source: CdkDrag<T>;
}

Expand Down Expand Up @@ -121,6 +123,7 @@ export declare class CdkDragPreview<T = any> {
}

export interface CdkDragRelease<T = any> {
event: MouseEvent | TouchEvent;
source: CdkDrag<T>;
}

Expand All @@ -132,6 +135,7 @@ export interface CdkDragSortEvent<T = any, I = T> {
}

export interface CdkDragStart<T = any> {
event: MouseEvent | TouchEvent;
source: CdkDrag<T>;
}

Expand Down Expand Up @@ -239,10 +243,12 @@ export declare class DragRef<T = any> {
previousContainer: DropListRef;
distance: Point;
isPointerOverContainer: boolean;
event: TouchEvent | MouseEvent;
}>;
ended: Subject<{
source: DragRef<any>;
distance: Point;
event: TouchEvent | MouseEvent;
}>;
entered: Subject<{
container: DropListRef;
Expand All @@ -269,9 +275,11 @@ export declare class DragRef<T = any> {
}>;
released: Subject<{
source: DragRef<any>;
event: TouchEvent | MouseEvent;
}>;
started: Subject<{
source: DragRef<any>;
event: TouchEvent | MouseEvent;
}>;
constructor(element: ElementRef<HTMLElement> | HTMLElement, _config: DragRefConfig, _document: Document, _ngZone: NgZone, _viewportRuler: ViewportRuler, _dragDropRegistry: DragDropRegistry<DragRef, DropListRef>);
_sortFromLastPointerPosition(): void;
Expand Down Expand Up @@ -311,6 +319,7 @@ export declare class DropListRef<T = any> {
previousContainer: DropListRef<any>;
isPointerOverContainer: boolean;
distance: Point;
event: TouchEvent | MouseEvent;
}>;
element: HTMLElement | ElementRef<HTMLElement>;
enterPredicate: (drag: DragRef, drop: DropListRef) => boolean;
Expand Down Expand Up @@ -347,7 +356,7 @@ export declare class DropListRef<T = any> {
_stopScrolling(): void;
connectedTo(connectedTo: DropListRef[]): this;
dispose(): void;
drop(item: DragRef, currentIndex: number, previousContainer: DropListRef, isPointerOverContainer: boolean, distance?: Point): void;
drop(item: DragRef, currentIndex: number, previousContainer: DropListRef, isPointerOverContainer: boolean, distance?: Point, event?: MouseEvent | TouchEvent): void;
enter(item: DragRef, pointerX: number, pointerY: number): void;
exit(item: DragRef): void;
getItemIndex(item: DragRef): number;
Expand Down

0 comments on commit 7b3c5bd

Please sign in to comment.