[FIX] component: do not call willPatch/patched if not in DOM

closes #62
This commit is contained in:
Géry Debongnie
2019-04-26 15:30:59 +02:00
parent b6bd0f92a7
commit b44f274e37
3 changed files with 49 additions and 4 deletions
+4 -2
View File
@@ -275,7 +275,8 @@ scrollbar.
Note that modifying the state object is not allowed here. This method is called just
before an actual DOM patch, and is only intended to be used to save some local
DOM state.
DOM state. Also, it will not be called if the widget is not in the DOM (this can
happen with widgets with `t-keepalive`).
The return value of this method will be given as the first argument of the
corresponding `patched` call.
@@ -287,7 +288,8 @@ likely via a change in its state/props or environment).
This method is not called on the initial render. It is useful to interact
with the DOM (for example, through an external library) whenever the
component was patched.
component was patched. Note that this hook will not be called if the widget is
not in the DOM (this can happen with widgets with `t-keepalive`).
The `snapshot` parameter is the result of the previous `willPatch` call.
+5 -2
View File
@@ -329,9 +329,12 @@ export class Component<
_patch(vnode) {
this.__owl__.renderPromise = null;
if (this.__owl__.vnode) {
const snapshot = this.willPatch();
const isMounted = this.__owl__.isMounted;
const snapshot = isMounted && this.willPatch();
this.__owl__.vnode = patch(this.__owl__.vnode, vnode);
this.patched(snapshot);
if (isMounted) {
this.patched(snapshot);
}
} else {
this.__owl__.vnode = patch(document.createElement(vnode.sel!), vnode);
}
+40
View File
@@ -575,6 +575,46 @@ describe("lifecycle hooks", () => {
"parent:patched"
]);
});
test("willPatch/patched hook with t-keepalive", async () => {
// we make sure here that willPatch/patched is only called if widget is in
// dom, mounted
const steps: string[] = [];
class ParentWidget extends Widget {
inlineTemplate = `
<div>
<t t-if="state.flag" t-widget="child" t-props="{v: state.n}" t-keepalive="1"/>
</div>`;
widgets = { child: ChildWidget };
state = { n: 1, flag: true };
}
class ChildWidget extends Widget {
willPatch() {
steps.push("child:willPatch");
}
patched() {
steps.push("child:patched");
}
willUnmount() {
steps.push("child:willUnmount");
}
mounted() {
steps.push("child:mounted");
}
}
const widget = new ParentWidget(env);
await widget.mount(fixture);
expect(steps).toEqual(['child:mounted']);
widget.state.flag = false;
await nextTick();
expect(steps).toEqual(['child:mounted', 'child:willUnmount']);
widget.state.flag = true;
await nextTick();
expect(steps).toEqual(['child:mounted', 'child:willUnmount', 'child:mounted']);
});
});
describe("destroy method", () => {