Skip to content

Commit

Permalink
fix(cdk/drag-drop): don't disable native dragging on inactive handles (
Browse files Browse the repository at this point in the history
…#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 f133210)
  • Loading branch information
crisbeto authored and wagnermaciel committed Nov 17, 2020
1 parent a5ab829 commit dcf870d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
34 changes: 33 additions & 1 deletion src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -5558,7 +5589,7 @@ class StandaloneDraggableSvgWithViewBox {

@Component({
template: `
<div #dragElement cdkDrag
<div #dragElement cdkDrag [cdkDragDisabled]="draggingDisabled"
style="width: 100px; height: 100px; background: red; position: relative">
<div #handleElement cdkDragHandle style="width: 10px; height: 10px; background: green;"></div>
</div>
Expand All @@ -5569,6 +5600,7 @@ class StandaloneDraggableWithHandle {
@ViewChild('handleElement') handleElement: ElementRef<HTMLElement>;
@ViewChild(CdkDrag) dragInstance: CdkDrag;
@ViewChild(CdkDragHandle) handleInstance: CdkDragHandle;
draggingDisabled = false;
}

@Component({
Expand Down
11 changes: 8 additions & 3 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ export class DragRef<T = any> {
if (newValue !== this._disabled) {
this._disabled = newValue;
this._toggleNativeDragInteractions();
this._handles.forEach(handle => toggleNativeDragInteractions(handle, newValue));
}
}
private _disabled = false;
Expand Down Expand Up @@ -342,7 +343,7 @@ export class DragRef<T = any> {
/** Registers the handles that can be used to drag the element. */
withHandles(handles: (HTMLElement | ElementRef<HTMLElement>)[]): 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;
}
Expand Down Expand Up @@ -458,8 +459,9 @@ export class DragRef<T = any> {
* @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);
}
}

Expand All @@ -468,7 +470,10 @@ export class DragRef<T = any> {
* @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. */
Expand Down

0 comments on commit dcf870d

Please sign in to comment.