From 87aa8312e42e841bdac8b2b53bfc17b830362f45 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 5 Feb 2019 21:26:49 +0100 Subject: [PATCH] fix(drag-drop): allow for element in DropListRef to be changed It doesn't look like there's a good reason to have the `element` be readonly, aside from minimizing the coercion logic, since we only use the element in a handful of places and we don't bind any events to it so we don't need any cleanup logic. These changes allow for the element to be swapped out by removing the `readonly`. Fixes #15086. --- src/cdk/drag-drop/drag-ref.ts | 2 +- src/cdk/drag-drop/drop-list-ref.ts | 13 ++++++++----- tools/public_api_guard/cdk/drag-drop.d.ts | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index c67b3bfa9f10..736a59310e2d 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -700,7 +700,7 @@ export class DragRef { if (this._nextSibling) { this._nextSibling.parentNode!.insertBefore(this._rootElement, this._nextSibling); } else { - this._initialContainer.element.appendChild(this._rootElement); + coerceElement(this._initialContainer.element).appendChild(this._rootElement); } this._destroyPreview(); diff --git a/src/cdk/drag-drop/drop-list-ref.ts b/src/cdk/drag-drop/drop-list-ref.ts index 6bb790d0d09c..9b90c1047c6a 100644 --- a/src/cdk/drag-drop/drop-list-ref.ts +++ b/src/cdk/drag-drop/drop-list-ref.ts @@ -9,6 +9,7 @@ import {ElementRef} from '@angular/core'; import {DragDropRegistry} from './drag-drop-registry'; import {Direction} from '@angular/cdk/bidi'; +import {coerceElement} from '@angular/cdk/coercion'; import {Subject} from 'rxjs'; import {moveItemInArray} from './drag-utils'; import {DragRefInternal as DragRef} from './drag-ref'; @@ -51,7 +52,7 @@ export class DropListRef { private _document: Document; /** Element that the drop list is attached to. */ - readonly element: HTMLElement; + element: HTMLElement | ElementRef; /** * Unique ID for the drop list. @@ -227,7 +228,7 @@ export class DropListRef { element.parentElement!.insertBefore(placeholder, element); activeDraggables.splice(newIndex, 0, item); } else { - this.element.appendChild(placeholder); + coerceElement(this.element).appendChild(placeholder); activeDraggables.push(item); } @@ -413,7 +414,7 @@ export class DropListRef { /** Caches the position of the drop list. */ private _cacheOwnPosition() { - this._clientRect = this.element.getBoundingClientRect(); + this._clientRect = coerceElement(this.element).getBoundingClientRect(); } /** Refreshes the position cache of the items and sibling containers. */ @@ -597,7 +598,7 @@ export class DropListRef { return false; } - const elementFromPoint = this._document.elementFromPoint(x, y); + const elementFromPoint = this._document.elementFromPoint(x, y) as HTMLElement | null; // If there's no element at the pointer position, then // the client rect is probably scrolled out of the view. @@ -605,13 +606,15 @@ export class DropListRef { return false; } + const nativeElement = coerceElement(this.element); + // The `ClientRect`, that we're using to find the container over which the user is // hovering, doesn't give us any information on whether the element has been scrolled // out of the view or whether it's overlapping with other containers. This means that // we could end up transferring the item into a container that's invisible or is positioned // below another one. We use the result from `elementFromPoint` to get the top-most element // at the pointer position and to find whether it's one of the intersecting drop containers. - return elementFromPoint === this.element || this.element.contains(elementFromPoint); + return elementFromPoint === nativeElement || nativeElement.contains(elementFromPoint); } /** diff --git a/tools/public_api_guard/cdk/drag-drop.d.ts b/tools/public_api_guard/cdk/drag-drop.d.ts index b52fa6bebc76..61b0e05e6ccd 100644 --- a/tools/public_api_guard/cdk/drag-drop.d.ts +++ b/tools/public_api_guard/cdk/drag-drop.d.ts @@ -279,7 +279,7 @@ export declare class DropListRef { previousContainer: DropListRef; isPointerOverContainer: boolean; }>; - readonly element: HTMLElement; + element: HTMLElement | ElementRef; enterPredicate: (drag: DragRef, drop: DropListRef) => boolean; entered: Subject<{ item: DragRef;