From 436809cba0c4fd52d418dc024de98a9bf56f4552 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 3 Nov 2018 01:22:17 +0100 Subject: [PATCH] fix(drag-drop): multiple parallel drag sequences when dragging nested drag items (#13820) Currently if we have a `cdkDrag` nested inside another `cdkDrag`, the user can start dragging both of the items at the same time if they starting dragging from the appropriate area. These change stop event propagation so only one drag sequence can be started from a certain area at a time. --- src/cdk/drag-drop/drag.spec.ts | 14 ++++++++++++++ src/cdk/drag-drop/drag.ts | 7 +++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cdk/drag-drop/drag.spec.ts b/src/cdk/drag-drop/drag.spec.ts index dfd428a9e8c..a927d090eca 100644 --- a/src/cdk/drag-drop/drag.spec.ts +++ b/src/cdk/drag-drop/drag.spec.ts @@ -412,6 +412,20 @@ describe('CdkDrag', () => { expect(dragElement.style.transform).toBeFalsy(); })); + it('should stop propagation for the drag sequence start event', fakeAsync(() => { + const fixture = createComponent(StandaloneDraggable); + fixture.detectChanges(); + const dragElement = fixture.componentInstance.dragElement.nativeElement; + + const event = createMouseEvent('mousedown'); + spyOn(event, 'stopPropagation').and.callThrough(); + + dispatchEvent(dragElement, event); + fixture.detectChanges(); + + expect(event.stopPropagation).toHaveBeenCalled(); + })); + }); describe('draggable with a handle', () => { diff --git a/src/cdk/drag-drop/drag.ts b/src/cdk/drag-drop/drag.ts index f26e2e004b5..5dc354f4b9d 100644 --- a/src/cdk/drag-drop/drag.ts +++ b/src/cdk/drag-drop/drag.ts @@ -329,10 +329,13 @@ export class CdkDrag implements AfterViewInit, OnDestroy { * @param event Browser event object that started the sequence. */ private _initializeDragSequence(referenceElement: HTMLElement, event: MouseEvent | TouchEvent) { - const isDragging = this._isDragging(); + // Always stop propagation for the event that initializes + // the dragging sequence, in order to prevent it from potentially + // starting another sequence for a draggable parent somewhere up the DOM tree. + event.stopPropagation(); // Abort if the user is already dragging or is using a mouse button other than the primary one. - if (isDragging || (!this._isTouchEvent(event) && event.button !== 0)) { + if (this._isDragging() || (!this._isTouchEvent(event) && event.button !== 0)) { return; }