Skip to content

Commit 43c7a7d

Browse files
crisbetommalerba
authored andcommitted
feat(drag-drop): allow drag start delay to be configured based… (#17301)
Allows the consumer to configure the drag start delay based on whether it's a touch event or mouse event. Fixes #17260.
1 parent 7a748fc commit 43c7a7d

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,27 @@ describe('CdkDrag', () => {
993993
'Expected element to be dragged after all the time has passed.');
994994
}));
995995

996+
it('should be able to configure the drag start delay based on the event type', fakeAsync(() => {
997+
// We can't use Jasmine's `clock` because Zone.js interferes with it.
998+
spyOn(Date, 'now').and.callFake(() => currentTime);
999+
let currentTime = 0;
1000+
1001+
const fixture = createComponent(StandaloneDraggable);
1002+
fixture.componentInstance.dragStartDelay = {touch: 500, mouse: 0};
1003+
fixture.detectChanges();
1004+
const dragElement = fixture.componentInstance.dragElement.nativeElement;
1005+
1006+
expect(dragElement.style.transform).toBeFalsy('Expected element not to be moved by default.');
1007+
1008+
dragElementViaTouch(fixture, dragElement, 50, 100);
1009+
expect(dragElement.style.transform)
1010+
.toBeFalsy('Expected element not to be moved via touch because it has a delay.');
1011+
1012+
dragElementViaMouse(fixture, dragElement, 50, 100);
1013+
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)',
1014+
'Expected element to be moved via mouse because it has no delay.');
1015+
}));
1016+
9961017
it('should be able to get the current position', fakeAsync(() => {
9971018
const fixture = createComponent(StandaloneDraggable);
9981019
fixture.detectChanges();
@@ -4293,7 +4314,7 @@ class StandaloneDraggable {
42934314
endedSpy = jasmine.createSpy('ended spy');
42944315
releasedSpy = jasmine.createSpy('released spy');
42954316
boundary: string | HTMLElement;
4296-
dragStartDelay: number | string;
4317+
dragStartDelay: number | string | {touch: number, mouse: number};
42974318
constrainPosition: (point: Point) => Point;
42984319
freeDragPosition?: {x: number, y: number};
42994320
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
118118
* Amount of milliseconds to wait after the user has put their
119119
* pointer down before starting to drag the element.
120120
*/
121-
@Input('cdkDragStartDelay') dragStartDelay: number = 0;
121+
@Input('cdkDragStartDelay') dragStartDelay: number | {touch: number, mouse: number} = 0;
122122

123123
/**
124124
* Sets the position of a `CdkDrag` that is outside of a drop container.
@@ -326,6 +326,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
326326
ref.beforeStarted.subscribe(() => {
327327
if (!ref.isDragging()) {
328328
const dir = this._dir;
329+
const dragStartDelay = this.dragStartDelay;
329330
const placeholder = this._placeholderTemplate ? {
330331
template: this._placeholderTemplate.templateRef,
331332
context: this._placeholderTemplate.data,
@@ -339,7 +340,8 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
339340

340341
ref.disabled = this.disabled;
341342
ref.lockAxis = this.lockAxis;
342-
ref.dragStartDelay = coerceNumberProperty(this.dragStartDelay);
343+
ref.dragStartDelay = (typeof dragStartDelay === 'object' && dragStartDelay) ?
344+
dragStartDelay : coerceNumberProperty(dragStartDelay);
343345
ref.constrainPosition = this.constrainPosition;
344346
ref
345347
.withBoundaryElement(this._getBoundaryElement())

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export class DragRef<T = any> {
208208
* Amount of milliseconds to wait after the user has put their
209209
* pointer down before starting to drag the element.
210210
*/
211-
dragStartDelay: number = 0;
211+
dragStartDelay: number | {touch: number, mouse: number} = 0;
212212

213213
/** Whether starting to drag this element is disabled. */
214214
get disabled(): boolean {
@@ -533,7 +533,7 @@ export class DragRef<T = any> {
533533
// in the `pointerMove` subscription, because we're not guaranteed to have one move event
534534
// per pixel of movement (e.g. if the user moves their pointer quickly).
535535
if (isOverThreshold) {
536-
const isDelayElapsed = Date.now() >= this._dragStartTime + (this.dragStartDelay || 0);
536+
const isDelayElapsed = Date.now() >= this._dragStartTime + this._getDragStartDelay(event);
537537
if (!isDelayElapsed) {
538538
this._endDragSequence(event);
539539
return;
@@ -1149,6 +1149,19 @@ export class DragRef<T = any> {
11491149
this.setFreeDragPosition({y, x});
11501150
}
11511151
}
1152+
1153+
/** Gets the drag start delay, based on the event type. */
1154+
private _getDragStartDelay(event: MouseEvent | TouchEvent): number {
1155+
const value = this.dragStartDelay;
1156+
1157+
if (typeof value === 'number') {
1158+
return value;
1159+
} else if (isTouchEvent(event)) {
1160+
return value.touch;
1161+
}
1162+
1163+
return value ? value.mouse : 0;
1164+
}
11521165
}
11531166

11541167
/** Point on the page or within an element. */

tools/public_api_guard/cdk/drag-drop.d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDes
1313
constrainPosition?: (point: Point, dragRef: DragRef) => Point;
1414
data: T;
1515
disabled: boolean;
16-
dragStartDelay: number;
16+
dragStartDelay: number | {
17+
touch: number;
18+
mouse: number;
19+
};
1720
dropContainer: CdkDropList;
1821
dropped: EventEmitter<CdkDragDrop<any>>;
1922
element: ElementRef<HTMLElement>;
@@ -194,7 +197,10 @@ export declare class DragRef<T = any> {
194197
constrainPosition?: (point: Point, dragRef: DragRef) => Point;
195198
data: T;
196199
disabled: boolean;
197-
dragStartDelay: number;
200+
dragStartDelay: number | {
201+
touch: number;
202+
mouse: number;
203+
};
198204
dropped: Subject<{
199205
previousIndex: number;
200206
currentIndex: number;

0 commit comments

Comments
 (0)