mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
fix: force children to rerender when env changes
This commit is contained in:
+12
-8
@@ -224,11 +224,11 @@ export class Component<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async render(): Promise<void> {
|
async render(force: boolean = false): Promise<void> {
|
||||||
if (this.__widget__.isDestroyed) {
|
if (this.__widget__.isDestroyed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const renderVDom = this._render();
|
const renderVDom = this._render(force);
|
||||||
const renderId = this.__widget__.renderId;
|
const renderId = this.__widget__.renderId;
|
||||||
const vnode = await renderVDom;
|
const vnode = await renderVDom;
|
||||||
if (renderId === this.__widget__.renderId) {
|
if (renderId === this.__widget__.renderId) {
|
||||||
@@ -281,16 +281,19 @@ export class Component<
|
|||||||
}
|
}
|
||||||
Object.assign(this.env, nextEnv);
|
Object.assign(this.env, nextEnv);
|
||||||
if (this.__widget__.isMounted) {
|
if (this.__widget__.isMounted) {
|
||||||
return this.render();
|
return this.render(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProps(nextProps: Props): Promise<void> {
|
async updateProps(
|
||||||
if (nextProps === this.__widget__.renderProps) {
|
nextProps: Props,
|
||||||
|
forceUpdate: boolean = false
|
||||||
|
): Promise<void> {
|
||||||
|
if (nextProps === this.__widget__.renderProps && !forceUpdate) {
|
||||||
await this.__widget__.renderPromise;
|
await this.__widget__.renderPromise;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const shouldUpdate = this.shouldUpdate(nextProps);
|
const shouldUpdate = forceUpdate || this.shouldUpdate(nextProps);
|
||||||
return shouldUpdate ? this._updateProps(nextProps) : Promise.resolve();
|
return shouldUpdate ? this._updateProps(nextProps) : Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,13 +351,14 @@ export class Component<
|
|||||||
return this.__widget__.renderPromise;
|
return this.__widget__.renderPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _render(): Promise<VNode> {
|
async _render(force: boolean = false): Promise<VNode> {
|
||||||
this.__widget__.renderId++;
|
this.__widget__.renderId++;
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
const template = this.inlineTemplate || this.template;
|
const template = this.inlineTemplate || this.template;
|
||||||
let vnode = this.env.qweb.render(template, this, {
|
let vnode = this.env.qweb.render(template, this, {
|
||||||
promises,
|
promises,
|
||||||
handlers: this.__widget__.boundHandlers
|
handlers: this.__widget__.boundHandlers,
|
||||||
|
forceUpdate: force
|
||||||
});
|
});
|
||||||
|
|
||||||
// this part is critical for the patching process to be done correctly. The
|
// this part is critical for the patching process to be done correctly. The
|
||||||
|
|||||||
+6
-2
@@ -947,7 +947,9 @@ const widgetDirective: Directive = {
|
|||||||
// check if we can reuse current rendering promise
|
// check if we can reuse current rendering promise
|
||||||
ctx.addIf(`w${widgetID} && w${widgetID}.__widget__.renderPromise`);
|
ctx.addIf(`w${widgetID} && w${widgetID}.__widget__.renderPromise`);
|
||||||
ctx.addIf(`w${widgetID}.__widget__.isStarted`);
|
ctx.addIf(`w${widgetID}.__widget__.isStarted`);
|
||||||
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID});`);
|
ctx.addLine(
|
||||||
|
`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`
|
||||||
|
);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`isNew${widgetID} = true`);
|
ctx.addLine(`isNew${widgetID} = true`);
|
||||||
ctx.addIf(`props${widgetID} === w${widgetID}.__widget__.renderProps`);
|
ctx.addIf(`props${widgetID} === w${widgetID}.__widget__.renderProps`);
|
||||||
@@ -961,7 +963,9 @@ const widgetDirective: Directive = {
|
|||||||
|
|
||||||
ctx.addIf(`!def${defID}`);
|
ctx.addIf(`!def${defID}`);
|
||||||
ctx.addIf(`w${widgetID}`);
|
ctx.addIf(`w${widgetID}`);
|
||||||
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID});`);
|
ctx.addLine(
|
||||||
|
`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`
|
||||||
|
);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`w${widgetID} = new context.widgets['${value}'](owner, props${widgetID});`
|
`w${widgetID} = new context.widgets['${value}'](owner, props${widgetID});`
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
|||||||
let isNew7 = !w7;
|
let isNew7 = !w7;
|
||||||
if (w7 && w7.__widget__.renderPromise) {
|
if (w7 && w7.__widget__.renderPromise) {
|
||||||
if (w7.__widget__.isStarted) {
|
if (w7.__widget__.isStarted) {
|
||||||
def6 = w7.updateProps(props7);
|
def6 = w7.updateProps(props7, extra.forceUpdate);
|
||||||
} else {
|
} else {
|
||||||
isNew7 = true
|
isNew7 = true
|
||||||
if (props7 === w7.__widget__.renderProps) {
|
if (props7 === w7.__widget__.renderProps) {
|
||||||
@@ -47,7 +47,7 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
|||||||
}
|
}
|
||||||
if (!def6) {
|
if (!def6) {
|
||||||
if (w7) {
|
if (w7) {
|
||||||
def6 = w7.updateProps(props7);
|
def6 = w7.updateProps(props7, extra.forceUpdate);
|
||||||
} else {
|
} else {
|
||||||
w7 = new context.widgets['ChildWidget'](owner, props7);
|
w7 = new context.widgets['ChildWidget'](owner, props7);
|
||||||
context.__widget__.cmap[key8] = w7.__widget__.id;
|
context.__widget__.cmap[key8] = w7.__widget__.id;
|
||||||
@@ -86,7 +86,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
|
|||||||
let isNew4 = !w4;
|
let isNew4 = !w4;
|
||||||
if (w4 && w4.__widget__.renderPromise) {
|
if (w4 && w4.__widget__.renderPromise) {
|
||||||
if (w4.__widget__.isStarted) {
|
if (w4.__widget__.isStarted) {
|
||||||
def3 = w4.updateProps(props4);
|
def3 = w4.updateProps(props4, extra.forceUpdate);
|
||||||
} else {
|
} else {
|
||||||
isNew4 = true
|
isNew4 = true
|
||||||
if (props4 === w4.__widget__.renderProps) {
|
if (props4 === w4.__widget__.renderProps) {
|
||||||
@@ -99,7 +99,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
|
|||||||
}
|
}
|
||||||
if (!def3) {
|
if (!def3) {
|
||||||
if (w4) {
|
if (w4) {
|
||||||
def3 = w4.updateProps(props4);
|
def3 = w4.updateProps(props4, extra.forceUpdate);
|
||||||
} else {
|
} else {
|
||||||
w4 = new context.widgets['child'](owner, props4);
|
w4 = new context.widgets['child'](owner, props4);
|
||||||
context.__widget__.cmap[key5] = w4.__widget__.id;
|
context.__widget__.cmap[key5] = w4.__widget__.id;
|
||||||
|
|||||||
@@ -1171,4 +1171,21 @@ describe("updating environment", () => {
|
|||||||
await widget.updateEnv(<any>{ someKey: "rerendered" });
|
await widget.updateEnv(<any>{ someKey: "rerendered" });
|
||||||
expect(fixture.innerHTML).toBe("<div>rerendered</div>");
|
expect(fixture.innerHTML).toBe("<div>rerendered</div>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("updating env force rerendering children", async () => {
|
||||||
|
class Parent extends Widget {
|
||||||
|
inlineTemplate = `<div><t t-widget="Child"/></div>`;
|
||||||
|
widgets = { Child };
|
||||||
|
}
|
||||||
|
class Child extends Widget {
|
||||||
|
inlineTemplate = `<div><t t-esc="env.someKey"/></div>`;
|
||||||
|
}
|
||||||
|
(<any>env).someKey = "hey";
|
||||||
|
const widget = new Parent(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div><div>hey</div></div>");
|
||||||
|
await widget.updateEnv(<any>{ someKey: "rerendered" });
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe("<div><div>rerendered</div></div>");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user