diff --git a/src/qweb.ts b/src/qweb.ts index 1dd49bb7..33fb8ceb 100644 --- a/src/qweb.ts +++ b/src/qweb.ts @@ -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;});` ); diff --git a/tests/component.test.ts b/tests/component.test.ts index eb4a0f33..2ecf89ec 100644 --- a/tests/component.test.ts +++ b/tests/component.test.ts @@ -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 = ` +
+ + +
`; + 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 = `
`;