mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] component: add support for callable expression in event handler
This commit is contained in:
committed by
Géry Debongnie
parent
3e0e8475a6
commit
7ebe0da962
@@ -75,6 +75,7 @@ export function makeHandlerCode(
|
|||||||
// we need to capture every variable in it
|
// we need to capture every variable in it
|
||||||
putInCache = false;
|
putInCache = false;
|
||||||
code = ctx.captureExpression(value);
|
code = ctx.captureExpression(value);
|
||||||
|
code = `const res = (() => { return ${code} })(); if (typeof res === 'function') { res(e) }`;
|
||||||
}
|
}
|
||||||
const modCode = mods.map((mod) => modcodes[mod]).join("");
|
const modCode = mods.map((mod) => modcodes[mod]).join("");
|
||||||
let handler = `function (e) {if (context.__owl__.status === ${STATUS.DESTROYED}){return}${modCode}${code}}`;
|
let handler = `function (e) {if (context.__owl__.status === ${STATUS.DESTROYED}){return}${modCode}${code}}`;
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ exports[`other directives with t-component t-on expression captured in t-foreach
|
|||||||
c6.push(vn7);
|
c6.push(vn7);
|
||||||
const otherState_8 = scope['otherState'];
|
const otherState_8 = scope['otherState'];
|
||||||
const iter_8 = scope.iter;
|
const iter_8 = scope.iter;
|
||||||
p7.on['click'] = function (e) {if (context.__owl__.status === 5){return}otherState_8.vals.push(iter_8+'_'+iter_8)};
|
p7.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return otherState_8.vals.push(iter_8+'_'+iter_8) })(); if (typeof res === 'function') { res(e) }};
|
||||||
c7.push({text: \`expr\`});
|
c7.push({text: \`expr\`});
|
||||||
utils.getScope(scope, 'iter').iter = scope.iter+1;
|
utils.getScope(scope, 'iter').iter = scope.iter+1;
|
||||||
}
|
}
|
||||||
@@ -630,7 +630,7 @@ exports[`other directives with t-component t-on expression in t-foreach 1`] = `
|
|||||||
c6.push(vn9);
|
c6.push(vn9);
|
||||||
const otherState_10 = scope['otherState'];
|
const otherState_10 = scope['otherState'];
|
||||||
const val_10 = scope['val'];
|
const val_10 = scope['val'];
|
||||||
p9.on['click'] = function (e) {if (context.__owl__.status === 5){return}otherState_10.vals.push(val_10)};
|
p9.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return otherState_10.vals.push(val_10) })(); if (typeof res === 'function') { res(e) }};
|
||||||
c9.push({text: \`Expr\`});
|
c9.push({text: \`Expr\`});
|
||||||
}
|
}
|
||||||
scope = _origScope5;
|
scope = _origScope5;
|
||||||
@@ -684,7 +684,7 @@ exports[`other directives with t-component t-on expression in t-foreach with t-s
|
|||||||
const otherState_10 = scope['otherState'];
|
const otherState_10 = scope['otherState'];
|
||||||
const val_10 = scope['val'];
|
const val_10 = scope['val'];
|
||||||
const bossa_10 = scope.bossa;
|
const bossa_10 = scope.bossa;
|
||||||
p9.on['click'] = function (e) {if (context.__owl__.status === 5){return}otherState_10.vals.push(val_10+'_'+bossa_10)};
|
p9.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return otherState_10.vals.push(val_10+'_'+bossa_10) })(); if (typeof res === 'function') { res(e) }};
|
||||||
c9.push({text: \`Expr\`});
|
c9.push({text: \`Expr\`});
|
||||||
}
|
}
|
||||||
scope = _origScope5;
|
scope = _origScope5;
|
||||||
@@ -1011,7 +1011,7 @@ exports[`other directives with t-component t-on with inline statement 1`] = `
|
|||||||
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
|
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
|
||||||
w3 = new W3(parent, props3);
|
w3 = new W3(parent, props3);
|
||||||
parent.__owl__.cmap['__4__'] = w3.__owl__.id;
|
parent.__owl__.cmap['__4__'] = w3.__owl__.id;
|
||||||
let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; utils.assignHooks(vnode.data, {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (context.__owl__.status === 5){return}state_5.counter++});}});});
|
let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; utils.assignHooks(vnode.data, {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (context.__owl__.status === 5){return}const res = (() => { return state_5.counter++ })(); if (typeof res === 'function') { res(e) }});}});});
|
||||||
let pvnode = h('dummy', {key: '__4__', hook: {remove() {},destroy(vn) {w3.destroy();}}});
|
let pvnode = h('dummy', {key: '__4__', hook: {remove() {},destroy(vn) {w3.destroy();}}});
|
||||||
c1.push(pvnode);
|
c1.push(pvnode);
|
||||||
w3.__owl__.pvnode = pvnode;
|
w3.__owl__.pvnode = pvnode;
|
||||||
|
|||||||
@@ -149,6 +149,24 @@ describe("basic widget properties", () => {
|
|||||||
expect(fixture.innerHTML).toBe("<div>1<button>Inc</button></div>");
|
expect(fixture.innerHTML).toBe("<div>1<button>Inc</button></div>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("support for callable expression in event handler", async () => {
|
||||||
|
class Counter extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<div><t t-esc="state.value"/><input type="text" t-on-input="obj.onInput"/></div>`;
|
||||||
|
state = useState({ value: "" });
|
||||||
|
obj = { onInput: (ev) => (this.state.value = ev.target.value) };
|
||||||
|
}
|
||||||
|
|
||||||
|
const counter = await mount(Counter, { target: fixture });
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(`<div><input type="text"></div>`);
|
||||||
|
const input = (<HTMLElement>counter.el).getElementsByTagName("input")[0];
|
||||||
|
input.value = "test";
|
||||||
|
input.dispatchEvent(new Event("input"));
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(`<div>test<input type="text"></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
test("can handle empty props", async () => {
|
test("can handle empty props", async () => {
|
||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
static template = xml`<span><t t-esc="props.val"/></span>`;
|
static template = xml`<span><t t-esc="props.val"/></span>`;
|
||||||
|
|||||||
@@ -2950,7 +2950,7 @@ exports[`t-on t-on with empty handler (only modifiers) 1`] = `
|
|||||||
let c2 = [], p2 = {key:2,on:{}};
|
let c2 = [], p2 = {key:2,on:{}};
|
||||||
let vn2 = h('button', p2, c2);
|
let vn2 = h('button', p2, c2);
|
||||||
c1.push(vn2);
|
c1.push(vn2);
|
||||||
p2.on['click'] = function (e) {if (context.__owl__.status === 5){return}e.preventDefault();};
|
p2.on['click'] = function (e) {if (context.__owl__.status === 5){return}e.preventDefault();const res = (() => { return })(); if (typeof res === 'function') { res(e) }};
|
||||||
c2.push({text: \`Button\`});
|
c2.push({text: \`Button\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -2965,7 +2965,7 @@ exports[`t-on t-on with inline statement (function call) 1`] = `
|
|||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
const state_2 = scope['state'];
|
const state_2 = scope['state'];
|
||||||
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}state_2.incrementCounter(2)};
|
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return state_2.incrementCounter(2) })(); if (typeof res === 'function') { res(e) }};
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -2980,7 +2980,7 @@ exports[`t-on t-on with inline statement 1`] = `
|
|||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
const state_2 = scope['state'];
|
const state_2 = scope['state'];
|
||||||
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}state_2.counter++};
|
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return state_2.counter++ })(); if (typeof res === 'function') { res(e) }};
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -2995,7 +2995,7 @@ exports[`t-on t-on with inline statement, part 2 1`] = `
|
|||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1,on:{}};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
const state_2 = scope['state'];
|
const state_2 = scope['state'];
|
||||||
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}state_2.flag=!state_2.flag};
|
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return state_2.flag=!state_2.flag })(); if (typeof res === 'function') { res(e) }};
|
||||||
c1.push({text: \`Toggle\`});
|
c1.push({text: \`Toggle\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -3011,7 +3011,7 @@ exports[`t-on t-on with inline statement, part 3 1`] = `
|
|||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
const state_2 = scope['state'];
|
const state_2 = scope['state'];
|
||||||
const someFunction_2 = scope['someFunction'];
|
const someFunction_2 = scope['someFunction'];
|
||||||
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}state_2.n=someFunction_2(3)};
|
p1.on['click'] = function (e) {if (context.__owl__.status === 5){return}const res = (() => { return state_2.n=someFunction_2(3) })(); if (typeof res === 'function') { res(e) }};
|
||||||
c1.push({text: \`Toggle\`});
|
c1.push({text: \`Toggle\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
|
|||||||
Reference in New Issue
Block a user