fix issue with subwidgets not being mounted/unmounted

This commit is contained in:
Géry Debongnie
2019-01-31 15:14:26 +01:00
parent ed35e0d8e4
commit 7e90aec028
6 changed files with 36 additions and 37 deletions
+13 -2
View File
@@ -230,13 +230,24 @@ export class Widget<T extends WEnv, Props> {
*/ */
_mount(vnode: VNode, elm: HTMLElement): VNode { _mount(vnode: VNode, elm: HTMLElement): VNode {
this.__widget__.vnode = patch(elm, vnode); this.__widget__.vnode = patch(elm, vnode);
this.__mount();
return this.__widget__.vnode;
}
__mount() {
if (this.__widget__.isMounted) {
return;
}
if (this.__widget__.parent) { if (this.__widget__.parent) {
if (this.__widget__.parent.__widget__.isMounted) { if (this.__widget__.parent!.__widget__.isMounted) {
this.__widget__.isMounted = true; this.__widget__.isMounted = true;
this.mounted(); this.mounted();
const children = this.__widget__.children;
for (let id in children) {
children[id].__mount();
}
} }
} }
return this.__widget__.vnode;
} }
private visitSubTree(callback: (w: Widget<T, any>) => boolean) { private visitSubTree(callback: (w: Widget<T, any>) => boolean) {
+1 -1
View File
@@ -755,7 +755,7 @@ const widgetDirective: Directive = {
ctx.addLine( ctx.addLine(
`def${defID} = w${widgetID}.updateProps(${props}).then(()=>{let vnode=h(w${widgetID}.__widget__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;c${ `def${defID} = w${widgetID}.updateProps(${props}).then(()=>{let vnode=h(w${widgetID}.__widget__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;c${
ctx.parentNode ctx.parentNode
}[_${dummyID}_index]=vnode;vnode.data.hook = {insert(a){a.elm.parentNode.replaceChild(w${widgetID}.el,a.elm);a.elm=w${widgetID}.el;},remove(){w${widgetID}.${ }[_${dummyID}_index]=vnode;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 ? "detach" : "destroy" keepAlive ? "detach" : "destroy"
}()}}});` }()}}});`
); );
-4
View File
@@ -11,10 +11,6 @@ export class Action extends Widget<Env, Props> {
template = `<div class="o_content"/>`; template = `<div class="o_content"/>`;
currentWidget: any; currentWidget: any;
mounted() {
this.setContentWidget();
}
shouldUpdate(nextProps: Props) { shouldUpdate(nextProps: Props) {
if (nextProps.stack !== this.props.stack) { if (nextProps.stack !== this.props.stack) {
this.props = nextProps; this.props = nextProps;
+2 -17
View File
@@ -22,31 +22,16 @@ const template = `
<t t-widget="ColorWidget" t-props="{color: state.color}"/> <t t-widget="ColorWidget" t-props="{color: state.color}"/>
<button t-on-click="addNotif(false)">Add notif</button> <button t-on-click="addNotif(false)">Add notif</button>
<button t-on-click="addNotif(true)">Add sticky notif</button> <button t-on-click="addNotif(true)">Add sticky notif</button>
<t t-foreach="state.test" t-as="number">
<t t-widget="ChildWidget" t-key="number"/>
</t>
</div> </div>
`; `;
let n = 1;
class ChildWidget extends Widget<Env, never> {
name = "c";
template = `<span><t t-esc="state.n"/></span>`;
constructor(parent) {
super(parent);
this.state = { n };
n++;
}
}
export class Discuss extends Widget<Env, {}> { export class Discuss extends Widget<Env, {}> {
name = "discuss"; name = "discuss";
template = template; template = template;
widgets = { Clock, Counter, ColorWidget, ChildWidget }; widgets = { Clock, Counter, ColorWidget };
state = { validcounter: true, color: "red", test: [1, 2, 3] }; state = { validcounter: true, color: "red" };
mounted() {}
resetCounter(ev: MouseEvent) { resetCounter(ev: MouseEvent) {
if (this.refs.counter instanceof Counter) { if (this.refs.counter instanceof Counter) {
this.refs.counter.updateState({ counter: 3 }); this.refs.counter.updateState({ counter: 3 });
+16 -13
View File
@@ -1,31 +1,34 @@
import { Widget } from "../core/widget"; import { Widget } from "../core/widget";
import { Env } from "../env"; import { Env } from "../env";
const template = `<div class="o_clock"><t t-esc="state.currentTime"/></div>`;
export class Clock extends Widget<Env, {}> { export class Clock extends Widget<Env, {}> {
name = "clock"; name = "clock";
template = template; template = `<div class="o_clock"><t t-esc="state.currentTime"/></div>`;
interval: any | undefined; timeout: any | undefined;
state = { state = {
currentTime: "" currentTime: ""
}; };
async willStart() {
this.updateTime();
}
mounted() { mounted() {
this.interval = setInterval(this.updateTime.bind(this), 500); this.updateTime();
this.startClock();
} }
willUnmount() { willUnmount() {
clearInterval(this.interval); clearTimeout(this.timeout);
} }
updateTime() { updateTime() {
this.updateState({ this.updateState({ currentTime: new Date().toLocaleTimeString() });
currentTime: new Date().toLocaleTimeString() }
});
startClock() {
const now = Date.now();
const offset = 1000 - (now % 1000);
this.timeout = setTimeout(() => {
this.updateTime();
this.startClock();
}, offset);
} }
} }
+4
View File
@@ -600,9 +600,13 @@ describe("composition", () => {
expect(fixture.innerHTML).toBe( expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>" "<div><div>1<button>Inc</button></div></div>"
); );
const counter = children(widget)[0];
expect(counter.__widget__.isMounted).toBe(true);
await widget.updateState({ ok: false }); await widget.updateState({ ok: false });
expect(fixture.innerHTML).toBe("<div></div>"); expect(fixture.innerHTML).toBe("<div></div>");
expect(counter.__widget__.isMounted).toBe(false);
await widget.updateState({ ok: true }); await widget.updateState({ ok: true });
expect(counter.__widget__.isMounted).toBe(true);
expect(fixture.innerHTML).toBe( expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>" "<div><div>1<button>Inc</button></div></div>"
); );