diff --git a/doc/component.md b/doc/component.md index 6dc63d43..b240eb74 100644 --- a/doc/component.md +++ b/doc/component.md @@ -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. diff --git a/src/component.ts b/src/component.ts index 4aabea2f..f08f9d59 100644 --- a/src/component.ts +++ b/src/component.ts @@ -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); } diff --git a/tests/component.test.ts b/tests/component.test.ts index 0be0d587..b8bf5a9a 100644 --- a/tests/component.test.ts +++ b/tests/component.test.ts @@ -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 = ` +