mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
allow multiple uses of t-on directive
This commit is contained in:
@@ -330,6 +330,8 @@ export class QWeb {
|
|||||||
fullName: string;
|
fullName: string;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
|
let withHandlers = false;
|
||||||
|
|
||||||
for (let directive of this.directives) {
|
for (let directive of this.directives) {
|
||||||
// const value = attributes[i].textContent!;
|
// const value = attributes[i].textContent!;
|
||||||
let fullName;
|
let fullName;
|
||||||
@@ -342,13 +344,13 @@ export class QWeb {
|
|||||||
) {
|
) {
|
||||||
fullName = name;
|
fullName = name;
|
||||||
value = attributes[i].textContent;
|
value = attributes[i].textContent;
|
||||||
|
validDirectives.push({ directive, value, fullName });
|
||||||
|
if (directive.name === "on") {
|
||||||
|
withHandlers = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fullName) {
|
|
||||||
validDirectives.push({ directive, value, fullName });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let { directive, value, fullName } of validDirectives) {
|
for (let { directive, value, fullName } of validDirectives) {
|
||||||
if (directive.atNodeEncounter) {
|
if (directive.atNodeEncounter) {
|
||||||
const isDone = directive.atNodeEncounter({
|
const isDone = directive.atNodeEncounter({
|
||||||
@@ -365,7 +367,7 @@ export class QWeb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.nodeName !== "t") {
|
if (node.nodeName !== "t") {
|
||||||
let nodeID = this._compileGenericNode(node, ctx);
|
let nodeID = this._compileGenericNode(node, ctx, withHandlers);
|
||||||
ctx = ctx.withParent(nodeID);
|
ctx = ctx.withParent(nodeID);
|
||||||
|
|
||||||
for (let { directive, value, fullName } of validDirectives) {
|
for (let { directive, value, fullName } of validDirectives) {
|
||||||
@@ -391,7 +393,11 @@ export class QWeb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_compileGenericNode(node: ChildNode, ctx: Context): number {
|
_compileGenericNode(
|
||||||
|
node: ChildNode,
|
||||||
|
ctx: Context,
|
||||||
|
withHandlers: boolean = true
|
||||||
|
): number {
|
||||||
// nodeType 1 is generic tag
|
// nodeType 1 is generic tag
|
||||||
if (node.nodeType !== 1) {
|
if (node.nodeType !== 1) {
|
||||||
throw new Error("unsupported node type");
|
throw new Error("unsupported node type");
|
||||||
@@ -458,11 +464,15 @@ export class QWeb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let nodeID = ctx.generateID();
|
let nodeID = ctx.generateID();
|
||||||
let p =
|
const parts = [`key:${nodeID}`];
|
||||||
attrs.length + tattrs.length > 0
|
if (attrs.length + tattrs.length > 0) {
|
||||||
? `{key:${nodeID},attrs:{${attrs.join(",")}}}`
|
parts.push(`attrs:{${attrs.join(",")}}`);
|
||||||
: `{key:${nodeID}}`;
|
}
|
||||||
ctx.addLine(`let c${nodeID} = [], p${nodeID} = ${p};`);
|
if (withHandlers) {
|
||||||
|
parts.push(`on:{}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.addLine(`let c${nodeID} = [], p${nodeID} = {${parts.join(",")}};`);
|
||||||
for (let id of tattrs) {
|
for (let id of tattrs) {
|
||||||
ctx.addIf(`_${id} instanceof Array`);
|
ctx.addIf(`_${id} instanceof Array`);
|
||||||
ctx.addLine(`p${nodeID}.attrs[_${id}[0]] = _${id}[1];`);
|
ctx.addLine(`p${nodeID}.attrs[_${id}[0]] = _${id}[1];`);
|
||||||
@@ -763,15 +773,17 @@ const onDirective: Directive = {
|
|||||||
});
|
});
|
||||||
if (extraArgs) {
|
if (extraArgs) {
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`p${nodeID}.on = {${eventName}: context['${handler}'].bind(owner, ${qweb._formatExpression(
|
`p${nodeID}.on['${eventName}'] = context['${handler}'].bind(owner, ${qweb._formatExpression(
|
||||||
extraArgs
|
extraArgs
|
||||||
)})};`
|
)});`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`extra.handlers[${nodeID}] = extra.handlers[${nodeID}] || context['${handler}'].bind(owner);`
|
`extra.handlers['${eventName}' + ${nodeID}] = extra.handlers['${eventName}' + ${nodeID}] || context['${handler}'].bind(owner);`
|
||||||
|
);
|
||||||
|
ctx.addLine(
|
||||||
|
`p${nodeID}.on['${eventName}'] = extra.handlers['${eventName}' + ${nodeID}];`
|
||||||
);
|
);
|
||||||
ctx.addLine(`p${nodeID}.on = {${eventName}: extra.handlers[${nodeID}]};`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ exports[`misc global 1`] = `
|
|||||||
context.value_value = _4[i];
|
context.value_value = _4[i];
|
||||||
c1.push({text: \`
|
c1.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let c5 = [], p5 = {key:5};
|
let c5 = [], p5 = {key:5,on:{}};
|
||||||
let vn5 = h('span', p5, c5);
|
let vn5 = h('span', p5, c5);
|
||||||
c1.push(vn5);
|
c1.push(vn5);
|
||||||
let e6 = context['value'];
|
let e6 = context['value'];
|
||||||
@@ -516,12 +516,12 @@ exports[`misc global 1`] = `
|
|||||||
c1.push({text: \`
|
c1.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let _7 = 'agüero';
|
let _7 = 'agüero';
|
||||||
let c8 = [], p8 = {key:8,attrs:{\\"falló\\": _7}};
|
let c8 = [], p8 = {key:8,attrs:{\\"falló\\": _7},on:{}};
|
||||||
let vn8 = h('Año', p8, c8);
|
let vn8 = h('Año', p8, c8);
|
||||||
c1.push(vn8);
|
c1.push(vn8);
|
||||||
c8.push({text: \`
|
c8.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let c9 = [], p9 = {key:9};
|
let c9 = [], p9 = {key:9,on:{}};
|
||||||
let vn9 = h('span', p9, c9);
|
let vn9 = h('span', p9, c9);
|
||||||
c8.push(vn9);
|
c8.push(vn9);
|
||||||
let e10 = 'aaa';
|
let e10 = 'aaa';
|
||||||
@@ -532,7 +532,7 @@ exports[`misc global 1`] = `
|
|||||||
}
|
}
|
||||||
c8.push({text: \`
|
c8.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let c11 = [], p11 = {key:11};
|
let c11 = [], p11 = {key:11,on:{}};
|
||||||
let vn11 = h('span', p11, c11);
|
let vn11 = h('span', p11, c11);
|
||||||
c8.push(vn11);
|
c8.push(vn11);
|
||||||
let e12 = context['foo'];
|
let e12 = context['foo'];
|
||||||
@@ -545,7 +545,7 @@ exports[`misc global 1`] = `
|
|||||||
\`});
|
\`});
|
||||||
c8.push({text: \`
|
c8.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let c13 = [], p13 = {key:13};
|
let c13 = [], p13 = {key:13,on:{}};
|
||||||
let vn13 = h('span', p13, c13);
|
let vn13 = h('span', p13, c13);
|
||||||
c8.push(vn13);
|
c8.push(vn13);
|
||||||
let e14 = 'bbb';
|
let e14 = 'bbb';
|
||||||
@@ -561,7 +561,7 @@ exports[`misc global 1`] = `
|
|||||||
}
|
}
|
||||||
c1.push({text: \`
|
c1.push({text: \`
|
||||||
\`});
|
\`});
|
||||||
let c15 = [], p15 = {key:15};
|
let c15 = [], p15 = {key:15,on:{}};
|
||||||
let vn15 = h('div', p15, c15);
|
let vn15 = h('div', p15, c15);
|
||||||
c1.push(vn15);
|
c1.push(vn15);
|
||||||
let e16 = context['toto'];
|
let e16 = context['toto'];
|
||||||
@@ -722,7 +722,7 @@ exports[`t-esc escaping on a node 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('span', p1, c1);
|
let vn1 = h('span', p1, c1);
|
||||||
let e2 = 'ok';
|
let e2 = 'ok';
|
||||||
if (e2 || e2 === 0) {
|
if (e2 || e2 === 0) {
|
||||||
@@ -736,7 +736,7 @@ exports[`t-esc escaping on a node with a body 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('span', p1, c1);
|
let vn1 = h('span', p1, c1);
|
||||||
let e2 = 'ok';
|
let e2 = 'ok';
|
||||||
if (e2 || e2 === 0) {
|
if (e2 || e2 === 0) {
|
||||||
@@ -752,7 +752,7 @@ exports[`t-esc escaping on a node with a body, as a default 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('span', p1, c1);
|
let vn1 = h('span', p1, c1);
|
||||||
let e2 = context['var'];
|
let e2 = context['var'];
|
||||||
if (e2 || e2 === 0) {
|
if (e2 || e2 === 0) {
|
||||||
@@ -914,10 +914,10 @@ exports[`t-on can bind event handler 1`] = `
|
|||||||
) {
|
) {
|
||||||
let owner = context;
|
let owner = context;
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
extra.handlers[1] = extra.handlers[1] || context['add'].bind(owner);
|
extra.handlers['click' + 1] = extra.handlers['click' + 1] || context['add'].bind(owner);
|
||||||
p1.on = {click: extra.handlers[1]};
|
p1.on['click'] = extra.handlers['click' + 1];
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -928,9 +928,9 @@ exports[`t-on can bind handlers with arguments 1`] = `
|
|||||||
) {
|
) {
|
||||||
let owner = context;
|
let owner = context;
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
p1.on = {click: context['add'].bind(owner, 5)};
|
p1.on['click'] = context['add'].bind(owner, 5);
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -961,10 +961,10 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
|||||||
let c5 = [], p5 = {key:5};
|
let c5 = [], p5 = {key:5};
|
||||||
let vn5 = h('li', p5, c5);
|
let vn5 = h('li', p5, c5);
|
||||||
c1.push(vn5);
|
c1.push(vn5);
|
||||||
let c6 = [], p6 = {key:6};
|
let c6 = [], p6 = {key:6,on:{}};
|
||||||
let vn6 = h('a', p6, c6);
|
let vn6 = h('a', p6, c6);
|
||||||
c5.push(vn6);
|
c5.push(vn6);
|
||||||
p6.on = {click: context['activate'].bind(owner, context['action'])};
|
p6.on['click'] = context['activate'].bind(owner, context['action']);
|
||||||
c6.push({text: \`link\`});
|
c6.push({text: \`link\`});
|
||||||
}
|
}
|
||||||
c1.push({text: \`
|
c1.push({text: \`
|
||||||
@@ -973,15 +973,31 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-on can bind two event handlers 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let owner = context;
|
||||||
|
let h = this.utils.h;
|
||||||
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
|
let vn1 = h('button', p1, c1);
|
||||||
|
extra.handlers['click' + 1] = extra.handlers['click' + 1] || context['handleClick'].bind(owner);
|
||||||
|
p1.on['click'] = extra.handlers['click' + 1];
|
||||||
|
extra.handlers['dblclick' + 1] = extra.handlers['dblclick' + 1] || context['handleDblClick'].bind(owner);
|
||||||
|
p1.on['dblclick'] = extra.handlers['dblclick' + 1];
|
||||||
|
c1.push({text: \`Click\`});
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-on handler is bound to proper owner 1`] = `
|
exports[`t-on handler is bound to proper owner 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let owner = context;
|
let owner = context;
|
||||||
let h = this.utils.h;
|
let h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
extra.handlers[1] = extra.handlers[1] || context['add'].bind(owner);
|
extra.handlers['click' + 1] = extra.handlers['click' + 1] || context['add'].bind(owner);
|
||||||
p1.on = {click: extra.handlers[1]};
|
p1.on['click'] = extra.handlers['click' + 1];
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -692,6 +692,32 @@ describe("t-on", () => {
|
|||||||
expect(a).toBe(3);
|
expect(a).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("can bind two event handlers", () => {
|
||||||
|
qweb.addTemplate(
|
||||||
|
"test",
|
||||||
|
`<button t-on-click="handleClick" t-on-dblclick="handleDblClick">Click</button>`
|
||||||
|
);
|
||||||
|
let steps: string[] = [];
|
||||||
|
const node = renderToDOM(
|
||||||
|
qweb,
|
||||||
|
"test",
|
||||||
|
{
|
||||||
|
handleClick() {
|
||||||
|
steps.push("click");
|
||||||
|
},
|
||||||
|
handleDblClick() {
|
||||||
|
steps.push("dblclick");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ handlers: [] }
|
||||||
|
);
|
||||||
|
expect(steps).toEqual([]);
|
||||||
|
(<HTMLElement>node).click();
|
||||||
|
expect(steps).toEqual(["click"]);
|
||||||
|
(<HTMLElement>node).dispatchEvent(new Event("dblclick"));
|
||||||
|
expect(steps).toEqual(["click", "dblclick"]);
|
||||||
|
});
|
||||||
|
|
||||||
test("can bind handlers with arguments", () => {
|
test("can bind handlers with arguments", () => {
|
||||||
qweb.addTemplate("test", `<button t-on-click="add(5)">Click</button>`);
|
qweb.addTemplate("test", `<button t-on-click="add(5)">Click</button>`);
|
||||||
let a = 1;
|
let a = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user