diff --git a/src/cdk/drag-drop/drag.spec.ts b/src/cdk/drag-drop/drag.spec.ts
index c56a3526b64c..8538d42c3c58 100644
--- a/src/cdk/drag-drop/drag.spec.ts
+++ b/src/cdk/drag-drop/drag.spec.ts
@@ -578,6 +578,13 @@ describe('CdkDrag', () => {
expect(dragElement.style.transform).toBe('translate3d(100px, 100px, 0px)');
}));
+ it('should throw if attached to an ng-container', fakeAsync(() => {
+ expect(() => {
+ createComponent(DraggableOnNgContainer).detectChanges();
+ flush();
+ }).toThrowError(/^cdkDrag must be attached to an element node/);
+ }));
+
});
describe('draggable with a handle', () => {
@@ -2766,6 +2773,15 @@ class NestedDropListGroups {
}
+@Component({
+ template: `
+
+ `
+})
+class DraggableOnNgContainer {}
+
+
+
/**
* Component that passes through whatever content is projected into it.
* Used to test having drag elements being projected into a component.
diff --git a/src/cdk/drag-drop/drag.ts b/src/cdk/drag-drop/drag.ts
index a59106226100..32dcd3a4e4ab 100644
--- a/src/cdk/drag-drop/drag.ts
+++ b/src/cdk/drag-drop/drag.ts
@@ -323,6 +323,12 @@ export class CdkDrag implements AfterViewInit, OnDestroy {
.pipe(take(1))
.subscribe(() => {
const rootElement = this._rootElement = this._getRootElement();
+
+ if (rootElement.nodeType !== this._document.ELEMENT_NODE) {
+ throw Error(`cdkDrag must be attached to an element node. ` +
+ `Currently attached to "${rootElement.nodeName}".`);
+ }
+
rootElement.addEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
rootElement.addEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
this._handles.changes.pipe(startWith(null)).subscribe(() =>