mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] qweb: t-on with t-widget: allow to bind args
This commit is contained in:
committed by
Géry Debongnie
parent
1c290c1172
commit
32921ecc20
+14
-6
@@ -183,7 +183,7 @@ QWeb.addDirective({
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
||||||
self: "if (e.target !== vn.elm) {return}",
|
self: "if (e.target !== vn.elm) {return}"
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -359,7 +359,7 @@ QWeb.addDirective({
|
|||||||
let keepAlive = node.getAttribute("t-keepalive") ? true : false;
|
let keepAlive = node.getAttribute("t-keepalive") ? true : false;
|
||||||
|
|
||||||
// t-on- events and t-transition
|
// t-on- events and t-transition
|
||||||
const events: [string, string[], string][] = [];
|
const events: [string, string[], string, string][] = [];
|
||||||
let transition: string = "";
|
let transition: string = "";
|
||||||
const attributes = (<Element>node).attributes;
|
const attributes = (<Element>node).attributes;
|
||||||
const props: { [key: string]: string } = {};
|
const props: { [key: string]: string } = {};
|
||||||
@@ -368,7 +368,12 @@ QWeb.addDirective({
|
|||||||
const value = attributes[i].textContent!;
|
const value = attributes[i].textContent!;
|
||||||
if (name.startsWith("t-on-")) {
|
if (name.startsWith("t-on-")) {
|
||||||
const [eventName, ...mods] = name.slice(5).split(".");
|
const [eventName, ...mods] = name.slice(5).split(".");
|
||||||
events.push([eventName, mods, value]);
|
let extraArgs;
|
||||||
|
let handlerName = value.replace(/\(.*\)/, function(args) {
|
||||||
|
extraArgs = args.slice(1, -1);
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
events.push([eventName, mods, handlerName, extraArgs]);
|
||||||
} else if (name === "t-transition") {
|
} else if (name === "t-transition") {
|
||||||
transition = value;
|
transition = value;
|
||||||
} else if (!name.startsWith("t-")) {
|
} else if (!name.startsWith("t-")) {
|
||||||
@@ -462,7 +467,10 @@ QWeb.addDirective({
|
|||||||
updateClassCode = `let cl=w${widgetID}.el.classList;for (let k in ${attVar}) {if (${attVar}[k]) {cl.add(k)} else {cl.remove(k)}}`;
|
updateClassCode = `let cl=w${widgetID}.el.classList;for (let k in ${attVar}) {if (${attVar}[k]) {cl.add(k)} else {cl.remove(k)}}`;
|
||||||
}
|
}
|
||||||
let eventsCode = events
|
let eventsCode = events
|
||||||
.map(function([eventName, mods, handlerName]) {
|
.map(function([eventName, mods, handlerName, extraArgs]) {
|
||||||
|
let params = extraArgs
|
||||||
|
? `owner, ${ctx.formatExpression(extraArgs)}`
|
||||||
|
: "owner";
|
||||||
let handler;
|
let handler;
|
||||||
if (mods.length > 0) {
|
if (mods.length > 0) {
|
||||||
handler = `function (e) {`;
|
handler = `function (e) {`;
|
||||||
@@ -471,9 +479,9 @@ QWeb.addDirective({
|
|||||||
return T_WIDGET_MODS_CODE[mod];
|
return T_WIDGET_MODS_CODE[mod];
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
handler += `owner['${handlerName}'].call(owner, e);}`;
|
handler += `owner['${handlerName}'].call(${params}, e);}`;
|
||||||
} else {
|
} else {
|
||||||
handler = `owner['${handlerName}'].bind(owner)`;
|
handler = `owner['${handlerName}'].bind(${params})`;
|
||||||
}
|
}
|
||||||
return `vn.elm.addEventListener('${eventName}', ${handler});`;
|
return `vn.elm.addEventListener('${eventName}', ${handler});`;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -222,6 +222,166 @@ exports[`composition t-widget with dynamic value 2 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`other directives with t-widget t-on with handler bound to argument 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let utils = this.utils;
|
||||||
|
let QWeb = this.constructor;
|
||||||
|
let owner = context;
|
||||||
|
var h = this.utils.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
//WIDGET
|
||||||
|
let _2_index = c1.length;
|
||||||
|
c1.push(null);
|
||||||
|
let def3;
|
||||||
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
|
let props4 = {};
|
||||||
|
if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
||||||
|
if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
||||||
|
def3 = w4.__owl__.renderPromise;
|
||||||
|
} else {
|
||||||
|
w4.destroy();
|
||||||
|
w4 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!w4) {
|
||||||
|
let widgetKey4 = \`child\`;
|
||||||
|
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
||||||
|
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
||||||
|
w4 = new W4(owner, props4);
|
||||||
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
|
def3 = w4._prepare();
|
||||||
|
def3 = def3.then(vnode=>{vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, 3));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||||
|
} else {
|
||||||
|
def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
||||||
|
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
|
||||||
|
}
|
||||||
|
extra.promises.push(def3);
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`other directives with t-widget t-on with handler bound to empty object (with non empty inner string) 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let utils = this.utils;
|
||||||
|
let QWeb = this.constructor;
|
||||||
|
let owner = context;
|
||||||
|
var h = this.utils.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
//WIDGET
|
||||||
|
let _2_index = c1.length;
|
||||||
|
c1.push(null);
|
||||||
|
let def3;
|
||||||
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
|
let props4 = {};
|
||||||
|
if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
||||||
|
if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
||||||
|
def3 = w4.__owl__.renderPromise;
|
||||||
|
} else {
|
||||||
|
w4.destroy();
|
||||||
|
w4 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!w4) {
|
||||||
|
let widgetKey4 = \`child\`;
|
||||||
|
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
||||||
|
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
||||||
|
w4 = new W4(owner, props4);
|
||||||
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
|
def3 = w4._prepare();
|
||||||
|
def3 = def3.then(vnode=>{vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||||
|
} else {
|
||||||
|
def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
||||||
|
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
|
||||||
|
}
|
||||||
|
extra.promises.push(def3);
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`other directives with t-widget t-on with handler bound to empty object 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let utils = this.utils;
|
||||||
|
let QWeb = this.constructor;
|
||||||
|
let owner = context;
|
||||||
|
var h = this.utils.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
//WIDGET
|
||||||
|
let _2_index = c1.length;
|
||||||
|
c1.push(null);
|
||||||
|
let def3;
|
||||||
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
|
let props4 = {};
|
||||||
|
if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
||||||
|
if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
||||||
|
def3 = w4.__owl__.renderPromise;
|
||||||
|
} else {
|
||||||
|
w4.destroy();
|
||||||
|
w4 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!w4) {
|
||||||
|
let widgetKey4 = \`child\`;
|
||||||
|
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
||||||
|
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
||||||
|
w4 = new W4(owner, props4);
|
||||||
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
|
def3 = w4._prepare();
|
||||||
|
def3 = def3.then(vnode=>{vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||||
|
} else {
|
||||||
|
def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
||||||
|
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
|
||||||
|
}
|
||||||
|
extra.promises.push(def3);
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`other directives with t-widget t-on with handler bound to object 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let utils = this.utils;
|
||||||
|
let QWeb = this.constructor;
|
||||||
|
let owner = context;
|
||||||
|
var h = this.utils.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
//WIDGET
|
||||||
|
let _2_index = c1.length;
|
||||||
|
c1.push(null);
|
||||||
|
let def3;
|
||||||
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
|
let props4 = {};
|
||||||
|
if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
||||||
|
if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
||||||
|
def3 = w4.__owl__.renderPromise;
|
||||||
|
} else {
|
||||||
|
w4.destroy();
|
||||||
|
w4 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!w4) {
|
||||||
|
let widgetKey4 = \`child\`;
|
||||||
|
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
||||||
|
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
||||||
|
w4 = new W4(owner, props4);
|
||||||
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
|
def3 = w4._prepare();
|
||||||
|
def3 = def3.then(vnode=>{vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {val: 3}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||||
|
} else {
|
||||||
|
def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
||||||
|
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
|
||||||
|
}
|
||||||
|
extra.promises.push(def3);
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with prevent and self modifiers (order matters) 1`] = `
|
exports[`other directives with t-widget t-on with prevent and self modifiers (order matters) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1173,7 +1173,7 @@ exports[`t-on can bind handlers with arguments 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`t-on can bind handlers with empty object (with non empty inner string 1`] = `
|
exports[`t-on can bind handlers with empty object (with non empty inner string) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let owner = context;
|
let owner = context;
|
||||||
|
|||||||
@@ -1476,6 +1476,94 @@ describe("other directives with t-widget", () => {
|
|||||||
expect(widget.n).toBe(1);
|
expect(widget.n).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-on with handler bound to argument", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
env.qweb.addTemplates(`
|
||||||
|
<templates>
|
||||||
|
<div t-name="ParentWidget"><t t-widget="child" t-on-ev="onEv(3)"/></div>
|
||||||
|
</templates>
|
||||||
|
`);
|
||||||
|
class ParentWidget extends Widget {
|
||||||
|
widgets = { child: Child };
|
||||||
|
onEv(n, ev) {
|
||||||
|
expect(n).toBe(3);
|
||||||
|
expect(ev.detail).toBe(43);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Child extends Widget {}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
let child = children(widget)[0];
|
||||||
|
child.trigger("ev", 43);
|
||||||
|
expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on with handler bound to object", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
env.qweb.addTemplates(`
|
||||||
|
<templates>
|
||||||
|
<div t-name="ParentWidget"><t t-widget="child" t-on-ev="onEv({val: 3})"/></div>
|
||||||
|
</templates>
|
||||||
|
`);
|
||||||
|
class ParentWidget extends Widget {
|
||||||
|
widgets = { child: Child };
|
||||||
|
onEv(o, ev) {
|
||||||
|
expect(o).toEqual({ val: 3 });
|
||||||
|
expect(ev.detail).toBe(43);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Child extends Widget {}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
let child = children(widget)[0];
|
||||||
|
child.trigger("ev", 43);
|
||||||
|
expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on with handler bound to empty object", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
env.qweb.addTemplates(`
|
||||||
|
<templates>
|
||||||
|
<div t-name="ParentWidget"><t t-widget="child" t-on-ev="onEv({})"/></div>
|
||||||
|
</templates>
|
||||||
|
`);
|
||||||
|
class ParentWidget extends Widget {
|
||||||
|
widgets = { child: Child };
|
||||||
|
onEv(o, ev) {
|
||||||
|
expect(o).toEqual({});
|
||||||
|
expect(ev.detail).toBe(43);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Child extends Widget {}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
let child = children(widget)[0];
|
||||||
|
child.trigger("ev", 43);
|
||||||
|
expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on with handler bound to empty object (with non empty inner string)", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
env.qweb.addTemplates(`
|
||||||
|
<templates>
|
||||||
|
<div t-name="ParentWidget"><t t-widget="child" t-on-ev="onEv({ })"/></div>
|
||||||
|
</templates>
|
||||||
|
`);
|
||||||
|
class ParentWidget extends Widget {
|
||||||
|
widgets = { child: Child };
|
||||||
|
onEv(o, ev) {
|
||||||
|
expect(o).toEqual({});
|
||||||
|
expect(ev.detail).toBe(43);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Child extends Widget {}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
let child = children(widget)[0];
|
||||||
|
child.trigger("ev", 43);
|
||||||
|
expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
test("t-on with stop and/or prevent modifiers", async () => {
|
test("t-on with stop and/or prevent modifiers", async () => {
|
||||||
expect.assertions(7);
|
expect.assertions(7);
|
||||||
env.qweb.addTemplates(`
|
env.qweb.addTemplates(`
|
||||||
|
|||||||
+1
-1
@@ -896,7 +896,7 @@ describe("t-on", () => {
|
|||||||
(<HTMLElement>node).click();
|
(<HTMLElement>node).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can bind handlers with empty object (with non empty inner string", () => {
|
test("can bind handlers with empty object (with non empty inner string)", () => {
|
||||||
expect.assertions(2);
|
expect.assertions(2);
|
||||||
qweb.addTemplate(
|
qweb.addTemplate(
|
||||||
"test",
|
"test",
|
||||||
|
|||||||
Reference in New Issue
Block a user