diff --git a/doc/reference/component.md b/doc/reference/component.md index b1d2e63b..c8adb8f5 100644 --- a/doc/reference/component.md +++ b/doc/reference/component.md @@ -448,7 +448,7 @@ The root component does not have a parent nor `props` (see note below). It will default empty environment). Note: a root component can however be given a `props` object in its constructor, -like this: `new App(null, {some: 'object'});`. It will not be a true `props` +like this: `new App(null, {some: 'object'});`. It will not be a true `props` object, managed by Owl (so, for example, it will never be updated). ### Composition diff --git a/src/component/component.ts b/src/component/component.ts index b2cd0ae5..20a29018 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -117,7 +117,7 @@ export class Component { let constr = this.constructor as any; const defaultProps = constr.defaultProps; if (defaultProps) { - props = props || {} as Props; + props = props || ({} as Props); this.__applyDefaultProps(props, defaultProps); } this.props = props; @@ -286,6 +286,11 @@ export class Component { } return; } + if (!(target instanceof HTMLElement)) { + let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`; + message += `\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`; + throw new Error(message); + } return new Promise((resolve, reject) => { const fiber = new Fiber(null, this, undefined, undefined, false); scheduler.addFiber(fiber, err => { diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index 1cf1653e..416ede23 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -91,6 +91,23 @@ describe("basic widget properties", () => { expect(fixture.innerHTML).toBe("
content
"); }); + test("display a nice message if mounted on a non existing node", async () => { + class SomeWidget extends Component { + static template = xml`
content
`; + } + const widget = new SomeWidget(); + let error; + try { + await widget.mount(null as any); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toBe( + "Component 'SomeWidget' cannot be mounted: the target is not a valid DOM node.\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)" + ); + }); + test("crashes if it cannot find a template", async () => { expect.assertions(1); class SomeWidget extends Component {}