diff --git a/demo/src/widgets/Discuss.ts b/demo/src/widgets/Discuss.ts
new file mode 100644
index 00000000..7c2e3c79
--- /dev/null
+++ b/demo/src/widgets/Discuss.ts
@@ -0,0 +1,40 @@
+import Widget from "../../../src/core/widget";
+import Counter from "./Counter";
+
+const template = `
+
+
Root Widget
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+export default class Discuss extends Widget {
+ name = "discuss";
+ template = template;
+ widgets = { Counter };
+ state = { validcounter: true };
+
+ resetCounter(ev: MouseEvent) {
+ this.refs.counter.updateState({ counter: 3 });
+ }
+
+ resetCounterAsync(ev: MouseEvent) {
+ setTimeout(() => {
+ this.refs.counter.updateState({ counter: 3 });
+ }, 3000);
+ }
+
+ toggle() {
+ this.updateState({ validcounter: !this.state.validcounter });
+ }
+}
diff --git a/demo/src/widgets/Navbar.ts b/demo/src/widgets/Navbar.ts
new file mode 100644
index 00000000..099913ed
--- /dev/null
+++ b/demo/src/widgets/Navbar.ts
@@ -0,0 +1,23 @@
+import Widget from "../../../src/core/widget";
+import { Action } from "../services/actions";
+
+const template = `
+
+`;
+
+export default class Navbar extends Widget {
+ name = "navbar";
+ template = template;
+
+ getUrl(action: Action) {
+ const action_id = action.id;
+ return this.env.services.router.formatURL("web", { action_id });
+ }
+}
diff --git a/demo/src/widgets/RootWidget.ts b/demo/src/widgets/RootWidget.ts
new file mode 100644
index 00000000..82f579a3
--- /dev/null
+++ b/demo/src/widgets/RootWidget.ts
@@ -0,0 +1,54 @@
+import Widget, { Env } from "../../../src/core/widget";
+import Navbar from "./Navbar";
+import { Action } from "../services/actions";
+
+const template = `
+
+`;
+
+export default class RootWidget extends Widget {
+ name = "root";
+ template = template;
+ widgets = { Navbar };
+ state = { validcounter: true };
+
+ constructor(env: Env) {
+ super(env);
+ this.setMainWidget();
+ }
+
+ mounted() {
+ this.env.services.router.register(this, this.onUrlChange);
+ }
+
+ setMainWidget() {
+ const action = this.getAction();
+ (
this.widgets).Content = action.Widget;
+ }
+
+ onUrlChange() {
+ this.setMainWidget();
+ // notice that this can only be safely done because the root widget is
+ // mounted now.
+ this.render();
+ }
+
+ getAction(): Action {
+ const routeInfo = this.env.services.router.getRouteInfo();
+ const actionID = parseInt(routeInfo.query.action_id);
+ let actions: Action[] = this.env.services.actions;
+ let action = actions.find(a => a.id === actionID);
+ if (!action) {
+ action = actions.find(a => a.default === true);
+ if (!action) {
+ throw new Error("No valid action!");
+ }
+ }
+ return action;
+ }
+}
diff --git a/package.json b/package.json
index 0345f963..cf8d6013 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"demo:build": "cp -r demo/ dist/demo && npm run demo:build:js && npm run demo:build:css",
"demo:build:css": "sass demo/app.scss dist/demo/app.css",
"demo:build:js": "tsc --allowjs -m amd --lib es2017,dom --target esnext --outfile dist/demo/main.js demo/src/main.ts",
- "demo:serve": "live-server dist/demo/",
+ "demo:serve": "live-server --entry-file=index.html dist/demo/",
"predemo:dev": "npm run demo:build",
"demo:dev": "npm-run-all --parallel \"demo:build:* -- --watch\" demo:serve"
},
diff --git a/src/core/widget.ts b/src/core/widget.ts
index 858ffd57..3a8aac2b 100644
--- a/src/core/widget.ts
+++ b/src/core/widget.ts
@@ -18,9 +18,9 @@ export default class Widget {
template: string = "";
vnode: VNode | null = null;
- parent: Widget | null;
+ parent: Widget | null = null;
children: Widget[] = [];
- env: Env | null = null;
+ env: Env;
el: HTMLElement | null = null;
state: Object = {};
refs: { [key: string]: Widget } = {};
@@ -29,13 +29,13 @@ export default class Widget {
// Lifecycle
//--------------------------------------------------------------------------
- constructor(parent: Widget | null, props?: any) {
- this.parent = parent;
- if (parent) {
+ constructor(parent: Widget | Env, props?: any) {
+ if (parent instanceof Widget) {
+ this.parent = parent;
parent.children.push(this);
- if (parent.env) {
- this.setEnvironment(parent.env);
- }
+ this.env = Object.create(parent.env);
+ } else {
+ this.env = parent;
}
}
@@ -59,7 +59,7 @@ export default class Widget {
if (target) {
target.appendChild(this.el!);
if (document.body.contains(target)) {
- this.visitSubTree(w => w.mounted())
+ this.visitSubTree(w => w.mounted());
}
}
return vnode;
@@ -71,10 +71,6 @@ export default class Widget {
}
}
- setEnvironment(env: Env) {
- this.env = Object.create(env);
- }
-
/**
* DOCSTRIGN
*
diff --git a/tests/widget.test.ts b/tests/widget.test.ts
index be9458e8..d5d6e3e8 100644
--- a/tests/widget.test.ts
+++ b/tests/widget.test.ts
@@ -6,8 +6,7 @@ function makeWidget(W: typeof Widget): Widget {
qweb: new QWeb(),
services: {}
};
- const w = new W(null);
- w.setEnvironment(env);
+ const w = new W(env);
return w;
}