mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
fix issue with subwidgets not being mounted/unmounted
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
}()}}});`
|
}()}}});`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 });
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>"
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user