diff --git a/src/core/qweb_vdom.ts b/src/core/qweb_vdom.ts
index cdc5686f..07e12dce 100644
--- a/src/core/qweb_vdom.ts
+++ b/src/core/qweb_vdom.ts
@@ -95,7 +95,8 @@ export default class QWeb {
elseDirective,
elifDirective,
ifDirective,
- callDirective
+ callDirective,
+ onDirective
].forEach(d => this.addDirective(d));
}
@@ -170,6 +171,9 @@ export default class QWeb {
* @param {string} name the template should already have been added
*/
render(name: string, context: any = {}): VNode {
+ if (!(name in this.rawTemplates)) {
+ throw new Error(`Template ${name} does not exist`);
+ }
const template = this.templates[name] || this._compile(name);
return template(context);
}
@@ -617,4 +621,22 @@ const forEachDirective: Directive = {
ctx.addLine("}");
return true;
}
-};
\ No newline at end of file
+};
+
+const onDirective: Directive = {
+ name: "on",
+ priority: 90,
+ atNodeCreation({ ctx, fullName, value, nodeID }) {
+ const eventName = fullName.slice(5);
+ let extraArgs;
+ let handler = value.replace(/\(.*\)/, function(args) {
+ extraArgs = args.slice(1, -1);
+ return "";
+ });
+ ctx.addLine(
+ `p${nodeID}.on = {${eventName}: context['${handler}'].bind(context${
+ extraArgs ? ", " + extraArgs : ""
+ })}`
+ );
+ }
+};
diff --git a/tests/qweb_vdom.test.ts b/tests/qweb_vdom.test.ts
index f7207bc2..9b49e864 100644
--- a/tests/qweb_vdom.test.ts
+++ b/tests/qweb_vdom.test.ts
@@ -5,10 +5,14 @@ import sdListeners from "../src/libs/snabbdom/src/modules/eventlisteners";
const patch = init([sdAttributes, sdListeners]);
-function qwebRender(qweb: QWeb, t: string, context: EvalContext = {}): string {
+function renderToDOM(qweb: QWeb, t: string, context: EvalContext = {}): HTMLElement {
const vnode = qweb.render(t, context);
const node = document.createElement(vnode.sel!);
patch(node, vnode);
+ return node;
+}
+function qwebRender(qweb: QWeb, t: string, context: EvalContext = {}): string {
+ const node = renderToDOM(qweb, t, context);
return node.outerHTML;
}
@@ -54,6 +58,13 @@ describe("error handling", () => {
"A template should have one root node"
);
});
+
+ test("nice warning if no template with given name", () => {
+ const qweb = new QWeb();
+ expect(() => qweb.render('invalidname')).toThrow('does not exist');
+ });
+
+
});
describe("t-esc", () => {
@@ -518,3 +529,28 @@ describe("misc", () => {
expect(qwebRender(qweb, "caller").trim()).toBe(expected);
});
});
+
+describe("t-on", () => {
+ test("can bind event handler", () => {
+ const qweb = new QWeb();
+ qweb.addTemplate('test', ``);
+ let a = 1;
+ const node = renderToDOM(qweb, 'test', {
+ add() { a = 3}
+ });
+ node.click();
+ expect(a).toBe(3);
+ });
+
+ test("can bind handlers with arguments", () => {
+ const qweb = new QWeb();
+ qweb.addTemplate('test', ``);
+ let a = 1;
+ const node = renderToDOM(qweb, 'test', {
+ add(n) { a = a + n}
+ });
+ node.click();
+ expect(a).toBe(6);
+ });
+});
+