diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts
index 30b4eca62e33..7cd3aeda05b2 100644
--- a/src/cdk/drag-drop/directives/drag.spec.ts
+++ b/src/cdk/drag-drop/directives/drag.spec.ts
@@ -694,7 +694,18 @@ describe('CdkDrag', () => {
it('should allow for dragging to be constrained to an element', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
- fixture.componentInstance.boundarySelector = '.wrapper';
+ fixture.componentInstance.boundary = '.wrapper';
+ fixture.detectChanges();
+ const dragElement = fixture.componentInstance.dragElement.nativeElement;
+
+ expect(dragElement.style.transform).toBeFalsy();
+ dragElementViaMouse(fixture, dragElement, 300, 300);
+ expect(dragElement.style.transform).toBe('translate3d(100px, 100px, 0px)');
+ }));
+
+ it('should be able to pass in a DOM node as the boundary', fakeAsync(() => {
+ const fixture = createComponent(StandaloneDraggable);
+ fixture.componentInstance.boundary = fixture.nativeElement.querySelector('.wrapper');
fixture.detectChanges();
const dragElement = fixture.componentInstance.dragElement.nativeElement;
@@ -3225,7 +3236,7 @@ describe('CdkDrag', () => {
Point;
freeDragPosition?: {x: number, y: number};
diff --git a/src/cdk/drag-drop/directives/drag.ts b/src/cdk/drag-drop/directives/drag.ts
index 7e33eec973fa..d8a30ca3327b 100644
--- a/src/cdk/drag-drop/directives/drag.ts
+++ b/src/cdk/drag-drop/directives/drag.ts
@@ -28,8 +28,9 @@ import {
OnChanges,
SimpleChanges,
ChangeDetectorRef,
+ isDevMode,
} from '@angular/core';
-import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
+import {coerceBooleanProperty, coerceNumberProperty, coerceElement} from '@angular/cdk/coercion';
import {Observable, Observer, Subject, merge} from 'rxjs';
import {startWith, take, map, takeUntil, switchMap, tap} from 'rxjs/operators';
import {
@@ -100,12 +101,27 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy {
*/
@Input('cdkDragRootElement') rootElementSelector: string;
+ /**
+ * Node or selector that will be used to determine the element to which the draggable's
+ * position will be constrained. If a string is passed in, it'll be used as a selector that
+ * will be matched starting from the element's parent and going up the DOM until a match
+ * has been found.
+ */
+ @Input('cdkDragBoundary') boundaryElement: string | ElementRef | HTMLElement;
+
/**
* Selector that will be used to determine the element to which the draggable's position will
* be constrained. Matching starts from the element's parent and goes up the DOM until a matching
- * element has been found.
+ * element has been found
+ * @deprecated Use `boundaryElement` instead.
+ * @breaking-change 9.0.0
*/
- @Input('cdkDragBoundary') boundaryElementSelector: string;
+ get boundaryElementSelector(): string {
+ return typeof this.boundaryElement === 'string' ? this.boundaryElement : undefined!;
+ }
+ set boundaryElementSelector(selector: string) {
+ this.boundaryElement = selector;
+ }
/**
* Amount of milliseconds to wait after the user has put their
@@ -292,10 +308,25 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy {
this._dragRef.withRootElement(rootElement || element);
}
- /** Gets the boundary element, based on the `boundaryElementSelector`. */
+ /** Gets the boundary element, based on the `boundaryElement` value. */
private _getBoundaryElement() {
- const selector = this.boundaryElementSelector;
- return selector ? getClosestMatchingAncestor(this.element.nativeElement, selector) : null;
+ const boundary = this.boundaryElement;
+
+ if (!boundary) {
+ return null;
+ }
+
+ if (typeof boundary === 'string') {
+ return getClosestMatchingAncestor(this.element.nativeElement, boundary);
+ }
+
+ const element = coerceElement(boundary);
+
+ if (isDevMode() && !element.contains(this.element.nativeElement)) {
+ throw Error('Draggable element is not inside of the node passed into cdkDragBoundary.');
+ }
+
+ return element;
}
/** Syncs the inputs of the CdkDrag with the options of the underlying DragRef. */
diff --git a/tools/public_api_guard/cdk/drag-drop.d.ts b/tools/public_api_guard/cdk/drag-drop.d.ts
index e94a7fafda05..8e5f158e8013 100644
--- a/tools/public_api_guard/cdk/drag-drop.d.ts
+++ b/tools/public_api_guard/cdk/drag-drop.d.ts
@@ -11,6 +11,7 @@ export declare class CdkDrag implements AfterViewInit, OnChanges, OnDes
_handles: QueryList;
_placeholderTemplate: CdkDragPlaceholder;
_previewTemplate: CdkDragPreview;
+ boundaryElement: string | ElementRef | HTMLElement;
boundaryElementSelector: string;
constrainPosition?: (point: Point) => Point;
data: T;