From 9fa3376dc42974493a7b34d7478d786b6e765c08 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 19 Dec 2018 16:07:33 +0100 Subject: [PATCH] fix(drag-drop): don't disable native drag interactions if dragging is disabled (#14233) Since consumers can use the `cdkDragDisabled` binding to disable dragging on an element, we shouldn't be disabling the native interactions unless we have to. These changes will only disable native interactions if dragging is enabled and there are no handles. --- src/cdk/drag-drop/directives/drag.spec.ts | 19 ++++++++++++++++--- src/cdk/drag-drop/directives/drag.ts | 1 + src/cdk/drag-drop/drag-ref.ts | 21 ++++++++++++++------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 9a085349d50..64db4880263 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -522,6 +522,20 @@ describe('CdkDrag', () => { expect(dragElement.style.transform).toBeFalsy(); })); + it('should enable native drag interactions if dragging is disabled', fakeAsync(() => { + const fixture = createComponent(StandaloneDraggable); + fixture.detectChanges(); + const dragElement = fixture.componentInstance.dragElement.nativeElement; + const styles = dragElement.style; + + expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none'); + + fixture.componentInstance.dragInstance.disabled = true; + fixture.detectChanges(); + + expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy(); + })); + it('should stop propagation for the drag sequence start event', fakeAsync(() => { const fixture = createComponent(StandaloneDraggable); fixture.detectChanges(); @@ -544,12 +558,11 @@ describe('CdkDrag', () => { }).not.toThrow(); })); - it('should not disable native drag interactions when there is a drag handle', () => { + it('should enable native drag interactions when there is a drag handle', () => { const fixture = createComponent(StandaloneDraggableWithHandle); fixture.detectChanges(); const dragElement = fixture.componentInstance.dragElement.nativeElement; - expect(dragElement.style.touchAction) - .not.toEqual('none', 'should not disable touchAction on when there is a drag handle'); + expect(dragElement.style.touchAction).not.toBe('none'); }); it('should be able to reset a freely-dragged item to its initial position', fakeAsync(() => { diff --git a/src/cdk/drag-drop/directives/drag.ts b/src/cdk/drag-drop/directives/drag.ts index bfbaf292e06..d0f23bc31e8 100644 --- a/src/cdk/drag-drop/directives/drag.ts +++ b/src/cdk/drag-drop/directives/drag.ts @@ -115,6 +115,7 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { } set disabled(value: boolean) { this._disabled = coerceBooleanProperty(value); + this._dragRef.disabled = this._disabled; } private _disabled = false; diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index b42119a4edf..dcf01427467 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -177,6 +177,9 @@ export class DragRef { /** Cached reference to the boundary element. */ private _boundaryElement: HTMLElement | null = null; + /** Whether the native dragging interactions have been enabled on the root element. */ + private _nativeInteractionsEnabled = true; + /** Cached dimensions of the preview element. */ private _previewRect?: ClientRect; @@ -192,9 +195,6 @@ export class DragRef { /** Elements that can be used to drag the draggable item. */ private _handles: DragHandle[] = []; - /** Whether the native interactions on the element are enabled. */ - private _nativeInteractionsEnabled = true; - /** Axis along which dragging is locked. */ lockAxis: 'x' | 'y'; @@ -203,7 +203,12 @@ export class DragRef { return this._disabled || !!(this.dropContainer && this.dropContainer.disabled); } set disabled(value: boolean) { - this._disabled = coerceBooleanProperty(value); + const newValue = coerceBooleanProperty(value); + + if (newValue !== this._disabled) { + this._disabled = newValue; + this._toggleNativeDragInteractions(); + } } private _disabled = false; @@ -911,10 +916,12 @@ export class DragRef { /** Toggles the native drag interactions, based on how many handles are registered. */ private _toggleNativeDragInteractions() { - const shouldEnable = this._handles.length > 0; + if (!this._rootElement || !this._handles) { + return; + } + + const shouldEnable = this.disabled || this._handles.length > 0; - // We go through the trouble of keeping track of whether the interactions are enabled, - // because we want to avoid triggering style recalculations unless we really have to. if (shouldEnable !== this._nativeInteractionsEnabled) { this._nativeInteractionsEnabled = shouldEnable; toggleNativeDragInteractions(this._rootElement, shouldEnable);