From 2674dbc3f419467e4f42fd283234944e931695d1 Mon Sep 17 00:00:00 2001 From: Maksym Makartsov Date: Mon, 2 Mar 2020 13:55:01 +0200 Subject: [PATCH] fix(cdk/drag-drop): drag&drop not working inside dialog if the page was scrolled Fixes a bug in Angular Material 'drag-drop' component where calculations in method '_getPointerPositionOnPage' was incorrect in situation when drag-drop container have fixed parent. Fixes #15880 --- src/cdk/drag-drop/directives/drag.ts | 5 +++++ src/cdk/drag-drop/drag-ref.ts | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/cdk/drag-drop/directives/drag.ts b/src/cdk/drag-drop/directives/drag.ts index 25530c37e4d5..f57ab81d2814 100644 --- a/src/cdk/drag-drop/directives/drag.ts +++ b/src/cdk/drag-drop/directives/drag.ts @@ -143,6 +143,10 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { /** Class to be added to the preview element. */ @Input('cdkDragPreviewClass') previewClass: string | string[]; + /** Whether parent of drag container is fixed. */ + @Input('cdkDropIsDragParentFixed') + dragParentFixed: boolean; + /** Emits when the user starts dragging the item. */ @Output('cdkDragStarted') started: EventEmitter = new EventEmitter(); @@ -372,6 +376,7 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { dragStartDelay : coerceNumberProperty(dragStartDelay); ref.constrainPosition = this.constrainPosition; ref.previewClass = this.previewClass; + ref.dragParentFixed = coerceBooleanProperty(this.dragParentFixed); ref .withBoundaryElement(this._getBoundaryElement()) .withPlaceholderTemplate(placeholder) diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index 556c599a8ce5..d56c69e997bb 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -292,6 +292,12 @@ export class DragRef { */ constrainPosition?: (point: Point, dragRef: DragRef) => Point; + /** + * Whether drag container is placed in + * dialog or other element that has a fixed position. + */ + dragParentFixed: boolean = false; + constructor( element: ElementRef | HTMLElement, private _config: DragRefConfig, @@ -1004,8 +1010,12 @@ export class DragRef { const handleElement = referenceElement === this._rootElement ? null : referenceElement; const referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect; const point = isTouchEvent(event) ? event.targetTouches[0] : event; - const x = point.pageX - referenceRect.left - this._scrollPosition.left; - const y = point.pageY - referenceRect.top - this._scrollPosition.top; + const x = this.dragParentFixed ? + point.pageX - referenceRect.left : + point.pageX - referenceRect.left - this._scrollPosition.left; + const y = this.dragParentFixed ? + point.pageY - referenceRect.top : + point.pageY - referenceRect.top - this._scrollPosition.top; return { x: referenceRect.left - elementRect.left + x, @@ -1019,8 +1029,8 @@ export class DragRef { const point = isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event; return { - x: point.pageX - this._scrollPosition.left, - y: point.pageY - this._scrollPosition.top + x: this.dragParentFixed ? point.pageX : point.pageX - this._scrollPosition.left, + y: this.dragParentFixed ? point.pageY : point.pageY - this._scrollPosition.top }; }