From 3cdc23078668ae6941aca8d83071876a90bcde9e Mon Sep 17 00:00:00 2001 From: crisbeto Date: Wed, 5 Dec 2018 22:03:52 +0100 Subject: [PATCH] fix(drag-drop): error on touch end Fixes an error being thrown by `CdkDrag` when the `touchend` event fires. Fixes #14390. --- src/cdk/drag-drop/drag.spec.ts | 24 ++++++++++++++++++++++++ src/cdk/drag-drop/drag.ts | 3 ++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/cdk/drag-drop/drag.spec.ts b/src/cdk/drag-drop/drag.spec.ts index 37f230e2e85e..ba9d47e7ee01 100644 --- a/src/cdk/drag-drop/drag.spec.ts +++ b/src/cdk/drag-drop/drag.spec.ts @@ -1895,6 +1895,30 @@ describe('CdkDrag', () => { .toEqual(['Zero', 'One', 'Two', 'Three']); })); + it('should not throw if the `touches` array is empty', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZone); + fixture.detectChanges(); + const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement; + + dispatchTouchEvent(item, 'touchstart'); + fixture.detectChanges(); + + dispatchTouchEvent(document, 'touchmove'); + fixture.detectChanges(); + + dispatchTouchEvent(document, 'touchmove', 50, 50); + fixture.detectChanges(); + + expect(() => { + const endEvent = createTouchEvent('touchend', 50, 50); + Object.defineProperty(endEvent, 'touches', {get: () => []}); + + dispatchEvent(document, endEvent); + fixture.detectChanges(); + }).not.toThrow(); + + })); + }); describe('in a connected drop container', () => { diff --git a/src/cdk/drag-drop/drag.ts b/src/cdk/drag-drop/drag.ts index 5e1ff12aba52..0e3b7d951354 100644 --- a/src/cdk/drag-drop/drag.ts +++ b/src/cdk/drag-drop/drag.ts @@ -790,7 +790,8 @@ export class CdkDrag implements AfterViewInit, OnDestroy { /** Determines the point of the page that was touched by the user. */ private _getPointerPositionOnPage(event: MouseEvent | TouchEvent): Point { - const point = this._isTouchEvent(event) ? event.touches[0] : event; + // `touches` will be empty for start/end events so we have to fall back to `changedTouches`. + const point = this._isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event; return { x: point.pageX - this._scrollPosition.left,