mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] component: t-refs are bound/unbound at proper timing
With this commit, we make sure that bound references are removed when a widget is removed from the DOM. closes #59
This commit is contained in:
committed by
Géry Debongnie
parent
4c2115d365
commit
379cd2a90f
+13
-9
@@ -1072,27 +1072,31 @@ const widgetDirective: Directive = {
|
||||
ctx.addLine(`w${widgetID}.on('${event}', owner, owner['${method}'])`);
|
||||
}
|
||||
let ref = node.getAttribute("t-ref");
|
||||
let refExpr = ref ? `context.refs[${ctx.formatExpression(ref)}] = w${widgetID};` : '';
|
||||
let refExpr = ref
|
||||
? `context.refs[${ctx.formatExpression(ref)}] = w${widgetID};`
|
||||
: "";
|
||||
|
||||
ctx.addLine(`def${defID} = w${widgetID}._prepare();`);
|
||||
ctx.closeIf();
|
||||
ctx.closeIf();
|
||||
|
||||
let finalizeWidgetCode = `w${widgetID}.${
|
||||
keepAlive ? "unmount" : "destroy"
|
||||
}()`;
|
||||
if (ref) {
|
||||
finalizeWidgetCode += `;delete context.refs[${ctx.formatExpression(
|
||||
ref
|
||||
)}]`;
|
||||
}
|
||||
ctx.addIf(`isNew${widgetID}`);
|
||||
ctx.addLine(
|
||||
`def${defID} = def${defID}.then(vnode=>{let pvnode=h(vnode.sel, {key: ${templateID}});c${
|
||||
ctx.parentNode
|
||||
}[_${dummyID}_index]=pvnode;pvnode.data.hook = {insert(vn){let nvn=w${widgetID}._mount(vnode, vn.elm);pvnode.elm=nvn.elm;${refExpr}},remove(){w${widgetID}.${
|
||||
keepAlive ? "unmount" : "destroy"
|
||||
}()},destroy(){w${widgetID}.${
|
||||
keepAlive ? "unmount" : "destroy"
|
||||
}()}}; w${widgetID}.__owl__.pvnode = pvnode;});`
|
||||
}[_${dummyID}_index]=pvnode;pvnode.data.hook = {insert(vn){let nvn=w${widgetID}._mount(vnode, vn.elm);pvnode.elm=nvn.elm;${refExpr}},remove(){${finalizeWidgetCode}},destroy(){${finalizeWidgetCode}}}; w${widgetID}.__owl__.pvnode = pvnode;});`
|
||||
);
|
||||
ctx.addElse();
|
||||
ctx.addLine(
|
||||
`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__owl__.isDestroyed) {return};let vnode;if (!w${widgetID}.__owl__.vnode){vnode=w${widgetID}.__owl__.pvnode} else { vnode=h(w${widgetID}.__owl__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;vnode.data.hook = {insert(a){a.elm.parentNode.replaceChild(w${widgetID}.el,a.elm);a.elm=w${widgetID}.el;w${widgetID}.__mount();},remove(){w${widgetID}.${
|
||||
keepAlive ? "unmount" : "destroy"
|
||||
}()}, destroy() {w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}}}c${
|
||||
`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__owl__.isDestroyed) {return};let vnode;if (!w${widgetID}.__owl__.vnode){vnode=w${widgetID}.__owl__.pvnode} else { vnode=h(w${widgetID}.__owl__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;vnode.data.hook = {insert(a){a.elm.parentNode.replaceChild(w${widgetID}.el,a.elm);a.elm=w${widgetID}.el;w${widgetID}.__mount();},remove(){${finalizeWidgetCode}}, destroy() {${finalizeWidgetCode}}}}c${
|
||||
ctx.parentNode
|
||||
}[_${dummyID}_index]=vnode;});`
|
||||
);
|
||||
|
||||
@@ -680,6 +680,52 @@ describe("composition", () => {
|
||||
await nextTick()
|
||||
});
|
||||
|
||||
test("t-refs are bound at proper timing (2)", async () => {
|
||||
expect.assertions(10);
|
||||
class ParentWidget extends Widget {
|
||||
inlineTemplate = `
|
||||
<div>
|
||||
<t t-if="state.child1" t-ref="'child1'" t-widget="Widget"/>
|
||||
<t t-if="state.child2" t-ref="'child2'" t-widget="Widget"/>
|
||||
</div>`;
|
||||
widgets = { Widget };
|
||||
state = { child1: true, child2: false };
|
||||
count = 0;
|
||||
mounted() {
|
||||
expect(this.refs.child1).toBeDefined();
|
||||
expect(this.refs.child2).toBeUndefined();
|
||||
}
|
||||
willPatch() {
|
||||
if (this.count === 0) {
|
||||
expect(this.refs.child1).toBeDefined();
|
||||
expect(this.refs.child2).toBeUndefined();
|
||||
}
|
||||
if (this.count === 1) {
|
||||
expect(this.refs.child1).toBeDefined();
|
||||
expect(this.refs.child2).toBeDefined();
|
||||
}
|
||||
}
|
||||
patched() {
|
||||
if (this.count === 0) {
|
||||
expect(this.refs.child1).toBeDefined();
|
||||
expect(this.refs.child2).toBeDefined();
|
||||
}
|
||||
if (this.count === 1) {
|
||||
expect(this.refs.child1).toBeUndefined();
|
||||
expect(this.refs.child2).toBeDefined();
|
||||
}
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
|
||||
const parent = new ParentWidget(env);
|
||||
await parent.mount(fixture);
|
||||
parent.state.child2 = true;
|
||||
await nextTick()
|
||||
parent.state.child1 = false;
|
||||
await nextTick()
|
||||
});
|
||||
|
||||
test("modifying a sub widget", async () => {
|
||||
class ParentWidget extends Widget {
|
||||
inlineTemplate = `<div><t t-widget="Counter"/></div>`;
|
||||
|
||||
Reference in New Issue
Block a user