From dcf870db6cbc7283f18fc159787ba89f0cddc539 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 17 Nov 2020 18:16:20 +0100 Subject: [PATCH] fix(cdk/drag-drop): don't disable native dragging on inactive handles (#20991) Currently we disable native drag interactions on handles once when they're registered, however this can block scrolling on mobile devices if the handle is inactive (either it is disabled or the drag element is disabled). These changes toggle the state dynamically depending on the active state. Fixes #20974. (cherry picked from commit f1332102210e02db857ae1cbb10d623937d5c231) --- src/cdk/drag-drop/directives/drag.spec.ts | 34 ++++++++++++++++++++++- src/cdk/drag-drop/drag-ref.ts | 11 ++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 12d3dd785e2d..a40a1aaf52ab 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -727,6 +727,37 @@ describe('CdkDrag', () => { expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none'); }); + it('should enable native drag interactions on the drag handle if dragging is disabled', () => { + const fixture = createComponent(StandaloneDraggableWithHandle); + fixture.detectChanges(); + fixture.componentInstance.draggingDisabled = true; + fixture.detectChanges(); + const styles = fixture.componentInstance.handleElement.nativeElement.style; + expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy(); + }); + + it('should enable native drag interactions on the drag handle if dragging is disabled ' + + 'on init', () => { + const fixture = createComponent(StandaloneDraggableWithHandle); + fixture.componentInstance.draggingDisabled = true; + fixture.detectChanges(); + const styles = fixture.componentInstance.handleElement.nativeElement.style; + expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy(); + }); + + it('should toggle native drag interactions based on whether the handle is disabled', () => { + const fixture = createComponent(StandaloneDraggableWithHandle); + fixture.detectChanges(); + fixture.componentInstance.handleInstance.disabled = true; + fixture.detectChanges(); + const styles = fixture.componentInstance.handleElement.nativeElement.style; + expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy(); + + fixture.componentInstance.handleInstance.disabled = false; + fixture.detectChanges(); + expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none'); + }); + it('should be able to reset a freely-dragged item to its initial position', fakeAsync(() => { const fixture = createComponent(StandaloneDraggable); fixture.detectChanges(); @@ -5558,7 +5589,7 @@ class StandaloneDraggableSvgWithViewBox { @Component({ template: ` -
@@ -5569,6 +5600,7 @@ class StandaloneDraggableWithHandle { @ViewChild('handleElement') handleElement: ElementRef; @ViewChild(CdkDrag) dragInstance: CdkDrag; @ViewChild(CdkDragHandle) handleInstance: CdkDragHandle; + draggingDisabled = false; } @Component({ diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index a967955e4574..8c46053651b4 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -249,6 +249,7 @@ export class DragRef { if (newValue !== this._disabled) { this._disabled = newValue; this._toggleNativeDragInteractions(); + this._handles.forEach(handle => toggleNativeDragInteractions(handle, newValue)); } } private _disabled = false; @@ -342,7 +343,7 @@ export class DragRef { /** Registers the handles that can be used to drag the element. */ withHandles(handles: (HTMLElement | ElementRef)[]): this { this._handles = handles.map(handle => coerceElement(handle)); - this._handles.forEach(handle => toggleNativeDragInteractions(handle, false)); + this._handles.forEach(handle => toggleNativeDragInteractions(handle, this.disabled)); this._toggleNativeDragInteractions(); return this; } @@ -458,8 +459,9 @@ export class DragRef { * @param handle Handle element that should be disabled. */ disableHandle(handle: HTMLElement) { - if (this._handles.indexOf(handle) > -1) { + if (!this._disabledHandles.has(handle) && this._handles.indexOf(handle) > -1) { this._disabledHandles.add(handle); + toggleNativeDragInteractions(handle, true); } } @@ -468,7 +470,10 @@ export class DragRef { * @param handle Handle element to be enabled. */ enableHandle(handle: HTMLElement) { - this._disabledHandles.delete(handle); + if (this._disabledHandles.has(handle)) { + this._disabledHandles.delete(handle); + toggleNativeDragInteractions(handle, this.disabled); + } } /** Sets the layout direction of the draggable item. */