Skip to content

Commit

Permalink
fix(drag-drop): throw better error when attaching to non-element node
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto committed Nov 27, 2018
1 parent 141afcf commit 0418466
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
19 changes: 18 additions & 1 deletion src/cdk/drag-drop/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ describe('CdkDrag', () => {
expect(dragElement.style.touchAction)
.not.toEqual('none', 'should not disable touchAction on when there is a drag handle');
});

it('should be able to reset a freely-dragged item to its initial position', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.detectChanges();
Expand Down Expand Up @@ -556,7 +557,14 @@ describe('CdkDrag', () => {
expect(fixture.componentInstance.endedSpy).toHaveBeenCalledTimes(1);
}));

});
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', () => {
it('should not be able to drag the entire element if it has a handle', fakeAsync(() => {
Expand Down Expand Up @@ -2631,6 +2639,15 @@ class NestedDropListGroups {
}


@Component({
template: `
<ng-container cdkDrag></ng-container>
`
})
class DraggableOnNgContainer {}



/**
* Component that passes through whatever content is projected into it.
* Used to test having drag elements being projected into a component.
Expand Down
6 changes: 6 additions & 0 deletions src/cdk/drag-drop/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ export class CdkDrag<T = any> 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(() =>
Expand Down

0 comments on commit 0418466

Please sign in to comment.