Skip to content

Commit 5686262

Browse files
committed
fix(cdk/drag-drop): stop pointer events on placeholder
Removes the pointer events from the drag placeholder so that the user can't interact with it while the preview is animating. Fixes #24403.
1 parent 599d1b4 commit 5686262

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ describe('CdkDrag', () => {
259259

260260
expect(dragElement.style.transform).toBeFalsy();
261261
}));
262+
263+
it('should prevent the default dragstart action', fakeAsync(() => {
264+
const fixture = createComponent(StandaloneDraggable);
265+
fixture.detectChanges();
266+
const event = dispatchFakeEvent(fixture.componentInstance.dragElement.nativeElement, 'dragstart');
267+
fixture.detectChanges();
268+
269+
expect(event.defaultPrevented).toBe(true);
270+
}));
262271
});
263272

264273
describe('touch dragging', () => {
@@ -2952,6 +2961,9 @@ describe('CdkDrag', () => {
29522961
expect(placeholder.textContent!.trim())
29532962
.withContext('Expected placeholder content to match element')
29542963
.toContain('One');
2964+
expect(placeholder.style.pointerEvents)
2965+
.withContext('Expected pointer events to be disabled on placeholder')
2966+
.toBe('none');
29552967

29562968
dispatchMouseEvent(document, 'mouseup');
29572969
fixture.detectChanges();

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ export class DragRef<T = any> {
442442
this._ngZone.runOutsideAngular(() => {
443443
element.addEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
444444
element.addEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
445+
// Usually this isn't necessary since the we prevent the default action in `pointerDown`,
446+
// but some cases like dragging of links can slip through (see #24403).
447+
element.addEventListener('dragstart', preventDefault, activeEventListenerOptions);
445448
});
446449
this._initialTransform = undefined;
447450
this._rootElement = element;
@@ -1159,6 +1162,9 @@ export class DragRef<T = any> {
11591162
placeholder = deepCloneNode(this._rootElement);
11601163
}
11611164

1165+
// Stop pointer events on the preview so the user can't
1166+
// interact with it while the preview is animating.
1167+
placeholder.style.pointerEvents = 'none';
11621168
placeholder.classList.add('cdk-drag-placeholder');
11631169
return placeholder;
11641170
}
@@ -1290,6 +1296,7 @@ export class DragRef<T = any> {
12901296
private _removeRootElementListeners(element: HTMLElement) {
12911297
element.removeEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
12921298
element.removeEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
1299+
element.removeEventListener('dragstart', preventDefault, activeEventListenerOptions);
12931300
}
12941301

12951302
/**
@@ -1555,3 +1562,8 @@ function matchElementSize(target: HTMLElement, sourceRect: ClientRect): void {
15551562
target.style.height = `${sourceRect.height}px`;
15561563
target.style.transform = getTransform(sourceRect.left, sourceRect.top);
15571564
}
1565+
1566+
/** Utility to prevent the default action of an event. */
1567+
function preventDefault(event: Event): void {
1568+
event.preventDefault();
1569+
}

0 commit comments

Comments
 (0)