mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb/component: do not call handlers for unmounted components
Unmounted components should be considered inactive, at least from the perspective of Owl itself. closes #543
This commit is contained in:
@@ -298,7 +298,7 @@ QWeb.addDirective({
|
||||
params = `owner, ${ctx.formatExpression(extraArgs)}`;
|
||||
}
|
||||
}
|
||||
let handler = `function (e) {`;
|
||||
let handler = `function (e) {if(!owner.__owl__.isMounted){return}`;
|
||||
handler += mods
|
||||
.map(function(mod) {
|
||||
return T_COMPONENT_MODS_CODE[mod];
|
||||
|
||||
@@ -41,7 +41,7 @@ QWeb.addDirective({
|
||||
return "";
|
||||
});
|
||||
let params = extraArgs ? `owner, ${ctx.formatExpression(extraArgs)}` : "owner";
|
||||
let handler = `function (e) {`;
|
||||
let handler = `function (e) {if (!context.__owl__.isMounted){return}`;
|
||||
handler += mods
|
||||
.map(function(mod) {
|
||||
return MODS_CODE[mod];
|
||||
|
||||
@@ -486,7 +486,7 @@ exports[`other directives with t-component t-on with getter as handler 1`] = `
|
||||
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
|
||||
w3 = new W3(parent, props3);
|
||||
parent.__owl__.cmap[k4] = w3.__owl__.id;
|
||||
let fiber = w3.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['handler'];if (fn) { fn.call(owner, e); } else { owner.handler; }});}};});
|
||||
let fiber = w3.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['handler'];if (fn) { fn.call(owner, e); } else { owner.handler; }});}};});
|
||||
let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w3.__owl__.pvnode = pvnode;
|
||||
@@ -524,7 +524,7 @@ exports[`other directives with t-component t-on with handler bound to argument 1
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, 3, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, 3, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -562,7 +562,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -600,7 +600,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -638,7 +638,7 @@ exports[`other directives with t-component t-on with handler bound to object 1`]
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {val:3}, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, {val:3}, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -680,7 +680,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 + '\\"')}
|
||||
w3 = new W3(parent, props3);
|
||||
parent.__owl__.cmap[k4] = w3.__owl__.id;
|
||||
let fiber = w3.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['state.counter++'];if (fn) { fn.call(owner, e); } else { owner.state.counter++; }});}};});
|
||||
let fiber = w3.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['state.counter++'];if (fn) { fn.call(owner, e); } else { owner.state.counter++; }});}};});
|
||||
let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w3.__owl__.pvnode = pvnode;
|
||||
@@ -718,7 +718,7 @@ exports[`other directives with t-component t-on with no handler (only modifiers)
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -756,7 +756,7 @@ exports[`other directives with t-component t-on with prevent and self modifiers
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {e.preventDefault();if (e.target !== vn.elm) {return}const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}e.preventDefault();if (e.target !== vn.elm) {return}const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -794,7 +794,7 @@ exports[`other directives with t-component t-on with self and prevent modifiers
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (e.target !== vn.elm) {return}e.preventDefault();const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}if (e.target !== vn.elm) {return}e.preventDefault();const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -832,7 +832,7 @@ exports[`other directives with t-component t-on with self modifier 1`] = `
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {if (e.target !== vn.elm) {return}const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {if(!owner.__owl__.isMounted){return}if (e.target !== vn.elm) {return}const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -870,7 +870,7 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie
|
||||
if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
|
||||
w2 = new W2(parent, props2);
|
||||
parent.__owl__.cmap[k3] = w2.__owl__.id;
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {e.stopPropagation();const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {e.preventDefault();const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});vn.elm.addEventListener('ev-3', function (e) {e.stopPropagation();e.preventDefault();const fn = owner['onEv3'];if (fn) { fn.call(owner, e); } else { owner.onEv3; }});}};});
|
||||
let fiber = w2.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {if(!owner.__owl__.isMounted){return}e.stopPropagation();const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {if(!owner.__owl__.isMounted){return}e.preventDefault();const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});vn.elm.addEventListener('ev-3', function (e) {if(!owner.__owl__.isMounted){return}e.stopPropagation();e.preventDefault();const fn = owner['onEv3'];if (fn) { fn.call(owner, e); } else { owner.onEv3; }});}};});
|
||||
let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w2.__owl__.pvnode = pvnode;
|
||||
@@ -981,7 +981,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument
|
||||
if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')}
|
||||
w6 = new W6(parent, props6);
|
||||
parent.__owl__.cmap[k7] = w6.__owl__.id;
|
||||
let fiber = w6.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, arg9, e); } else { owner.onEv; }});}};});
|
||||
let fiber = w6.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if(!owner.__owl__.isMounted){return}const fn = owner['onEv'];if (fn) { fn.call(owner, arg9, e); } else { owner.onEv; }});}};});
|
||||
let pvnode = h('dummy', {key: k7, hook: {remove() {},destroy(vn) {w6.destroy();}}});
|
||||
c1.push(pvnode);
|
||||
w6.__owl__.pvnode = pvnode;
|
||||
@@ -1400,7 +1400,7 @@ exports[`t-slot directive refs are properly bound in slots 1`] = `
|
||||
let c9 = [], p9 = {key:9,on:{}};
|
||||
var vn9 = h('button', p9, c9);
|
||||
c1.push(vn9);
|
||||
extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {const fn = context['doSomething'];if (fn) { fn.call(owner, e); } else { context.doSomething; }};
|
||||
extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(owner, e); } else { context.doSomething; }};
|
||||
p9.on['click'] = extra.handlers['click' + 9];
|
||||
const ref10 = \`myButton\`;
|
||||
p9.hook = {
|
||||
@@ -1425,7 +1425,7 @@ exports[`t-slot directive slots are rendered with proper context 1`] = `
|
||||
let c9 = [], p9 = {key:9,on:{}};
|
||||
var vn9 = h('button', p9, c9);
|
||||
c1.push(vn9);
|
||||
extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {const fn = context['doSomething'];if (fn) { fn.call(owner, e); } else { context.doSomething; }};
|
||||
extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(owner, e); } else { context.doSomething; }};
|
||||
p9.on['click'] = extra.handlers['click' + 9];
|
||||
c9.push({text: \`do something\`});
|
||||
}"
|
||||
|
||||
@@ -164,7 +164,7 @@ describe("basic widget properties", () => {
|
||||
button.click();
|
||||
await nextTick();
|
||||
expect(target.innerHTML).toBe("<div>0<button>Inc</button></div>");
|
||||
expect(counter.state.counter).toBe(1);
|
||||
expect(counter.state.counter).toBe(0);
|
||||
});
|
||||
|
||||
test("widget style and classname", async () => {
|
||||
@@ -2234,6 +2234,100 @@ describe("other directives with t-component", () => {
|
||||
expect(steps).toEqual(["GrandChild", "Child", "Parent"]);
|
||||
});
|
||||
|
||||
test("t-on on unmounted components", async () => {
|
||||
const steps: string[] = [];
|
||||
let child;
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<div t-on-click="onClick"/>`;
|
||||
mounted() {
|
||||
child = this;
|
||||
}
|
||||
onClick() {
|
||||
steps.push("click");
|
||||
}
|
||||
}
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`<div><Child/></div>`;
|
||||
static components = { Child };
|
||||
state = useState({ flag: true });
|
||||
}
|
||||
const parent = new Parent();
|
||||
await parent.mount(fixture);
|
||||
|
||||
let el = child.el;
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
parent.unmount();
|
||||
expect(child.__owl__.isMounted).toBe(false);
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
});
|
||||
|
||||
test("t-on on destroyed components", async () => {
|
||||
const steps: string[] = [];
|
||||
let child;
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<div t-on-click="onClick"/>`;
|
||||
mounted() {
|
||||
child = this;
|
||||
}
|
||||
onClick() {
|
||||
steps.push("click");
|
||||
}
|
||||
}
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`<div><Child t-if="state.flag"/></div>`;
|
||||
static components = { Child };
|
||||
state = useState({ flag: true });
|
||||
}
|
||||
const parent = new Parent();
|
||||
await parent.mount(fixture);
|
||||
|
||||
let el = child.el;
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
parent.state.flag = false;
|
||||
await nextTick();
|
||||
expect(child.__owl__.isDestroyed).toBe(true);
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
});
|
||||
|
||||
test("t-on on destroyed components, part 2", async () => {
|
||||
const steps: string[] = [];
|
||||
let child;
|
||||
class GrandChild extends Component<any, any> {
|
||||
static template = xml`<div>grandchild</div>`;
|
||||
}
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<div><GrandChild t-ref="gc" t-on-click="onClick"/></div>`;
|
||||
static components = { GrandChild };
|
||||
gc = useRef("gc");
|
||||
mounted() {
|
||||
child = this;
|
||||
}
|
||||
onClick() {
|
||||
steps.push("click");
|
||||
}
|
||||
}
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`<div><Child t-if="state.flag"/></div>`;
|
||||
static components = { Child };
|
||||
state = useState({ flag: true });
|
||||
}
|
||||
const parent = new Parent();
|
||||
await parent.mount(fixture);
|
||||
|
||||
let el = child.gc.el;
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
parent.state.flag = false;
|
||||
await nextTick();
|
||||
expect(child.__owl__.isDestroyed).toBe(true);
|
||||
el.click();
|
||||
expect(steps).toEqual(["click"]);
|
||||
});
|
||||
|
||||
test("t-if works with t-component", async () => {
|
||||
env.qweb.addTemplate("ParentWidget", `<div><t t-component="child" t-if="state.flag"/></div>`);
|
||||
class Child extends Widget {}
|
||||
|
||||
@@ -87,6 +87,11 @@ export function renderToDOM(
|
||||
context: EvalContext = {},
|
||||
extra?: any
|
||||
): HTMLElement | Text {
|
||||
if (!context.__owl__) {
|
||||
// we add `__owl__` to better simulate a component as context. This is
|
||||
// particularly important for event handlers added with the `t-on` directive.
|
||||
context.__owl__ = { isMounted: true };
|
||||
}
|
||||
const vnode = qweb.render(template, context, extra);
|
||||
|
||||
// we snapshot here the compiled code. This is useful to prevent unwanted code
|
||||
|
||||
@@ -1705,7 +1705,7 @@ exports[`t-on can bind event handler 1`] = `
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {const fn = context['add'];if (fn) { fn.call(owner, e); } else { context.add; }};
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['add'];if (fn) { fn.call(owner, e); } else { context.add; }};
|
||||
p1.on['click'] = extra.handlers['click' + 1];
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
@@ -1720,7 +1720,7 @@ exports[`t-on can bind handlers with arguments 1`] = `
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
const handler2 = context['add'] && context['add'].bind(owner, 5);
|
||||
p1.on['click'] = function (e) {if (handler2) { handler2(e); } else { context.add(5); }};
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler2) { handler2(e); } else { context.add(5); }};
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1734,7 +1734,7 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
const handler2 = context['doSomething'] && context['doSomething'].bind(owner, {});
|
||||
p1.on['click'] = function (e) {if (handler2) { handler2(e); } else { context.doSomething({ }); }};
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler2) { handler2(e); } else { context.doSomething({ }); }};
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1748,7 +1748,7 @@ exports[`t-on can bind handlers with empty object 1`] = `
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
const handler2 = context['doSomething'] && context['doSomething'].bind(owner, {});
|
||||
p1.on['click'] = function (e) {if (handler2) { handler2(e); } else { context.doSomething({}); }};
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler2) { handler2(e); } else { context.doSomething({}); }};
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1784,7 +1784,7 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
||||
var vn7 = h('a', p7, c7);
|
||||
c6.push(vn7);
|
||||
const handler8 = context['activate'] && context['activate'].bind(owner, context['action']);
|
||||
p7.on['click'] = function (e) {if (handler8) { handler8(e); } else { context.activate(action); }};
|
||||
p7.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler8) { handler8(e); } else { context.activate(action); }};
|
||||
c7.push({text: \`link\`});
|
||||
}
|
||||
return vn1;
|
||||
@@ -1799,7 +1799,7 @@ exports[`t-on can bind handlers with object arguments 1`] = `
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
const handler2 = context['add'] && context['add'].bind(owner, {val:5});
|
||||
p1.on['click'] = function (e) {if (handler2) { handler2(e); } else { context.add({val: 5}); }};
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler2) { handler2(e); } else { context.add({val: 5}); }};
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1812,9 +1812,9 @@ exports[`t-on can bind two event handlers 1`] = `
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {const fn = context['handleClick'];if (fn) { fn.call(owner, e); } else { context.handleClick; }};
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['handleClick'];if (fn) { fn.call(owner, e); } else { context.handleClick; }};
|
||||
p1.on['click'] = extra.handlers['click' + 1];
|
||||
extra.handlers['dblclick' + 1] = extra.handlers['dblclick' + 1] || function (e) {const fn = context['handleDblClick'];if (fn) { fn.call(owner, e); } else { context.handleDblClick; }};
|
||||
extra.handlers['dblclick' + 1] = extra.handlers['dblclick' + 1] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['handleDblClick'];if (fn) { fn.call(owner, e); } else { context.handleDblClick; }};
|
||||
p1.on['dblclick'] = extra.handlers['dblclick' + 1];
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
@@ -1828,7 +1828,7 @@ exports[`t-on handler is bound to proper owner 1`] = `
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {const fn = context['add'];if (fn) { fn.call(owner, e); } else { context.add; }};
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['add'];if (fn) { fn.call(owner, e); } else { context.add; }};
|
||||
p1.on['click'] = extra.handlers['click' + 1];
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
@@ -1845,7 +1845,7 @@ exports[`t-on t-on combined with t-esc 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
var _3 = context['text'];
|
||||
if (_3 || _3 === 0) {
|
||||
@@ -1866,7 +1866,7 @@ exports[`t-on t-on combined with t-raw 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
var _3 = context['html'];
|
||||
if (_3 || _3 === 0) {
|
||||
@@ -1886,7 +1886,7 @@ exports[`t-on t-on with empty handler (only modifiers) 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
p2.on['click'] = function (e) {e.preventDefault();};
|
||||
p2.on['click'] = function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();};
|
||||
c2.push({text: \`Button\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1900,7 +1900,7 @@ exports[`t-on t-on with inline statement (function call) 1`] = `
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
const handler2 = context['state.incrementCounter'] && context['state.incrementCounter'].bind(owner, 2);
|
||||
p1.on['click'] = function (e) {if (handler2) { handler2(e); } else { context.state.incrementCounter(2); }};
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}if (handler2) { handler2(e); } else { context.state.incrementCounter(2); }};
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
}"
|
||||
@@ -1913,7 +1913,7 @@ exports[`t-on t-on with inline statement 1`] = `
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {const fn = context['state.counter++'];if (fn) { fn.call(owner, e); } else { context.state.counter++; }};
|
||||
extra.handlers['click' + 1] = extra.handlers['click' + 1] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['state.counter++'];if (fn) { fn.call(owner, e); } else { context.state.counter++; }};
|
||||
p1.on['click'] = extra.handlers['click' + 1];
|
||||
c1.push({text: \`Click\`});
|
||||
return vn1;
|
||||
@@ -1930,7 +1930,7 @@ exports[`t-on t-on with prevent and self modifiers (order matters) 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {e.preventDefault();if (e.target !== this.elm) {return}const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();if (e.target !== this.elm) {return}const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
let c3 = [], p3 = {key:3};
|
||||
var vn3 = h('span', p3, c3);
|
||||
@@ -1950,19 +1950,19 @@ exports[`t-on t-on with prevent and/or stop modifiers 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {e.preventDefault();const fn = context['onClickPrevented'];if (fn) { fn.call(owner, e); } else { context.onClickPrevented; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();const fn = context['onClickPrevented'];if (fn) { fn.call(owner, e); } else { context.onClickPrevented; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
c2.push({text: \`Button 1\`});
|
||||
let c3 = [], p3 = {key:3,on:{}};
|
||||
var vn3 = h('button', p3, c3);
|
||||
c1.push(vn3);
|
||||
extra.handlers['click' + 3] = extra.handlers['click' + 3] || function (e) {e.stopPropagation();const fn = context['onClickStopped'];if (fn) { fn.call(owner, e); } else { context.onClickStopped; }};
|
||||
extra.handlers['click' + 3] = extra.handlers['click' + 3] || function (e) {if (!context.__owl__.isMounted){return}e.stopPropagation();const fn = context['onClickStopped'];if (fn) { fn.call(owner, e); } else { context.onClickStopped; }};
|
||||
p3.on['click'] = extra.handlers['click' + 3];
|
||||
c3.push({text: \`Button 2\`});
|
||||
let c4 = [], p4 = {key:4,on:{}};
|
||||
var vn4 = h('button', p4, c4);
|
||||
c1.push(vn4);
|
||||
extra.handlers['click' + 4] = extra.handlers['click' + 4] || function (e) {e.preventDefault();e.stopPropagation();const fn = context['onClickPreventedAndStopped'];if (fn) { fn.call(owner, e); } else { context.onClickPreventedAndStopped; }};
|
||||
extra.handlers['click' + 4] = extra.handlers['click' + 4] || function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();e.stopPropagation();const fn = context['onClickPreventedAndStopped'];if (fn) { fn.call(owner, e); } else { context.onClickPreventedAndStopped; }};
|
||||
p4.on['click'] = extra.handlers['click' + 4];
|
||||
c4.push({text: \`Button 3\`});
|
||||
return vn1;
|
||||
@@ -1997,7 +1997,7 @@ exports[`t-on t-on with prevent modifier in t-foreach 1`] = `
|
||||
var vn7 = h('a', p7, c7);
|
||||
c1.push(vn7);
|
||||
const handler8 = context['onEdit'] && context['onEdit'].bind(owner, context['project'].id);
|
||||
p7.on['click'] = function (e) {e.preventDefault();if (handler8) { handler8(e); } else { context.onEdit(project.id); }};
|
||||
p7.on['click'] = function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();if (handler8) { handler8(e); } else { context.onEdit(project.id); }};
|
||||
c7.push({text: \` Edit \`});
|
||||
var _9 = context['project'].name;
|
||||
if (_9 || _9 === 0) {
|
||||
@@ -2018,7 +2018,7 @@ exports[`t-on t-on with self and prevent modifiers (order matters) 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (e.target !== this.elm) {return}e.preventDefault();const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}if (e.target !== this.elm) {return}e.preventDefault();const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
let c3 = [], p3 = {key:3};
|
||||
var vn3 = h('span', p3, c3);
|
||||
@@ -2038,7 +2038,7 @@ exports[`t-on t-on with self modifier 1`] = `
|
||||
let c2 = [], p2 = {key:2,on:{}};
|
||||
var vn2 = h('button', p2, c2);
|
||||
c1.push(vn2);
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
extra.handlers['click' + 2] = extra.handlers['click' + 2] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['onClick'];if (fn) { fn.call(owner, e); } else { context.onClick; }};
|
||||
p2.on['click'] = extra.handlers['click' + 2];
|
||||
let c3 = [], p3 = {key:3};
|
||||
var vn3 = h('span', p3, c3);
|
||||
@@ -2047,7 +2047,7 @@ exports[`t-on t-on with self modifier 1`] = `
|
||||
let c4 = [], p4 = {key:4,on:{}};
|
||||
var vn4 = h('button', p4, c4);
|
||||
c1.push(vn4);
|
||||
extra.handlers['click' + 4] = extra.handlers['click' + 4] || function (e) {if (e.target !== this.elm) {return}const fn = context['onClickSelf'];if (fn) { fn.call(owner, e); } else { context.onClickSelf; }};
|
||||
extra.handlers['click' + 4] = extra.handlers['click' + 4] || function (e) {if (!context.__owl__.isMounted){return}if (e.target !== this.elm) {return}const fn = context['onClickSelf'];if (fn) { fn.call(owner, e); } else { context.onClickSelf; }};
|
||||
p4.on['click'] = extra.handlers['click' + 4];
|
||||
let c5 = [], p5 = {key:5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
|
||||
@@ -875,9 +875,9 @@ describe("foreach", () => {
|
||||
<t t-foreach="[1]" t-as="item"><t t-esc="item"/></t>
|
||||
</div>`
|
||||
);
|
||||
const context = {};
|
||||
const context = { __owl__: {} };
|
||||
renderToString(qweb, "test", context);
|
||||
expect(Object.keys(context).length).toBe(0);
|
||||
expect(Object.keys(context)).toEqual(["__owl__"]);
|
||||
});
|
||||
|
||||
test("t-foreach in t-forach", () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`Link component can render simple cases 1`] = `
|
||||
var _6 = context['href'];
|
||||
let c7 = [], p7 = {key:7,attrs:{href: _6},class:_5,on:{}};
|
||||
var vn7 = h('a', p7, c7);
|
||||
extra.handlers['click' + 7] = extra.handlers['click' + 7] || function (e) {const fn = context['navigate'];if (fn) { fn.call(owner, e); } else { context.navigate; }};
|
||||
extra.handlers['click' + 7] = extra.handlers['click' + 7] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['navigate'];if (fn) { fn.call(owner, e); } else { context.navigate; }};
|
||||
p7.on['click'] = extra.handlers['click' + 7];
|
||||
const slot8 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
|
||||
if (slot8) {
|
||||
|
||||
Reference in New Issue
Block a user