Skip to content

Commit dcf870d

Browse files
crisbetowagnermaciel
authored andcommitted
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 f133210)
1 parent a5ab829 commit dcf870d

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,37 @@ describe('CdkDrag', () => {
727727
expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none');
728728
});
729729

730+
it('should enable native drag interactions on the drag handle if dragging is disabled', () => {
731+
const fixture = createComponent(StandaloneDraggableWithHandle);
732+
fixture.detectChanges();
733+
fixture.componentInstance.draggingDisabled = true;
734+
fixture.detectChanges();
735+
const styles = fixture.componentInstance.handleElement.nativeElement.style;
736+
expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy();
737+
});
738+
739+
it('should enable native drag interactions on the drag handle if dragging is disabled ' +
740+
'on init', () => {
741+
const fixture = createComponent(StandaloneDraggableWithHandle);
742+
fixture.componentInstance.draggingDisabled = true;
743+
fixture.detectChanges();
744+
const styles = fixture.componentInstance.handleElement.nativeElement.style;
745+
expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy();
746+
});
747+
748+
it('should toggle native drag interactions based on whether the handle is disabled', () => {
749+
const fixture = createComponent(StandaloneDraggableWithHandle);
750+
fixture.detectChanges();
751+
fixture.componentInstance.handleInstance.disabled = true;
752+
fixture.detectChanges();
753+
const styles = fixture.componentInstance.handleElement.nativeElement.style;
754+
expect(styles.touchAction || (styles as any).webkitUserDrag).toBeFalsy();
755+
756+
fixture.componentInstance.handleInstance.disabled = false;
757+
fixture.detectChanges();
758+
expect(styles.touchAction || (styles as any).webkitUserDrag).toBe('none');
759+
});
760+
730761
it('should be able to reset a freely-dragged item to its initial position', fakeAsync(() => {
731762
const fixture = createComponent(StandaloneDraggable);
732763
fixture.detectChanges();
@@ -5558,7 +5589,7 @@ class StandaloneDraggableSvgWithViewBox {
55585589

55595590
@Component({
55605591
template: `
5561-
<div #dragElement cdkDrag
5592+
<div #dragElement cdkDrag [cdkDragDisabled]="draggingDisabled"
55625593
style="width: 100px; height: 100px; background: red; position: relative">
55635594
<div #handleElement cdkDragHandle style="width: 10px; height: 10px; background: green;"></div>
55645595
</div>
@@ -5569,6 +5600,7 @@ class StandaloneDraggableWithHandle {
55695600
@ViewChild('handleElement') handleElement: ElementRef<HTMLElement>;
55705601
@ViewChild(CdkDrag) dragInstance: CdkDrag;
55715602
@ViewChild(CdkDragHandle) handleInstance: CdkDragHandle;
5603+
draggingDisabled = false;
55725604
}
55735605

55745606
@Component({

src/cdk/drag-drop/drag-ref.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ export class DragRef<T = any> {
249249
if (newValue !== this._disabled) {
250250
this._disabled = newValue;
251251
this._toggleNativeDragInteractions();
252+
this._handles.forEach(handle => toggleNativeDragInteractions(handle, newValue));
252253
}
253254
}
254255
private _disabled = false;
@@ -342,7 +343,7 @@ export class DragRef<T = any> {
342343
/** Registers the handles that can be used to drag the element. */
343344
withHandles(handles: (HTMLElement | ElementRef<HTMLElement>)[]): this {
344345
this._handles = handles.map(handle => coerceElement(handle));
345-
this._handles.forEach(handle => toggleNativeDragInteractions(handle, false));
346+
this._handles.forEach(handle => toggleNativeDragInteractions(handle, this.disabled));
346347
this._toggleNativeDragInteractions();
347348
return this;
348349
}
@@ -458,8 +459,9 @@ export class DragRef<T = any> {
458459
* @param handle Handle element that should be disabled.
459460
*/
460461
disableHandle(handle: HTMLElement) {
461-
if (this._handles.indexOf(handle) > -1) {
462+
if (!this._disabledHandles.has(handle) && this._handles.indexOf(handle) > -1) {
462463
this._disabledHandles.add(handle);
464+
toggleNativeDragInteractions(handle, true);
463465
}
464466
}
465467

@@ -468,7 +470,10 @@ export class DragRef<T = any> {
468470
* @param handle Handle element to be enabled.
469471
*/
470472
enableHandle(handle: HTMLElement) {
471-
this._disabledHandles.delete(handle);
473+
if (this._disabledHandles.has(handle)) {
474+
this._disabledHandles.delete(handle);
475+
toggleNativeDragInteractions(handle, this.disabled);
476+
}
472477
}
473478

474479
/** Sets the layout direction of the draggable item. */

0 commit comments

Comments
 (0)