From 2943932998388633e834149599d5a76d4ff85709 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 20 Nov 2018 21:40:24 +0100 Subject: [PATCH] fix(drag-drop): throw better error when attaching to non-element node Currently if somebody attaches a `cdkDrag` to a non-element node (e.g. an `ng-container`), a cryptic error will be thrown. These changes log a proper error so it's easier to debug. --- src/cdk/drag-drop/drag.spec.ts | 16 ++++++++++++++++ src/cdk/drag-drop/drag.ts | 6 ++++++ 2 files changed, 22 insertions(+) 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(() =>