diff --git a/addons/web/static/src/core/utils/hooks.js b/addons/web/static/src/core/utils/hooks.js index 2fe6743a5c0..acf1c942a7b 100644 --- a/addons/web/static/src/core/utils/hooks.js +++ b/addons/web/static/src/core/utils/hooks.js @@ -216,7 +216,9 @@ export function useService(serviceName) { */ export function useChildRef() { let defined = false; - return function ref(value) { + let value; + return function ref(v) { + value = v; if (defined) { return; } diff --git a/addons/web/static/tests/core/utils/hooks_tests.js b/addons/web/static/tests/core/utils/hooks_tests.js index 4246df709f4..e0c33f84a30 100644 --- a/addons/web/static/tests/core/utils/hooks_tests.js +++ b/addons/web/static/tests/core/utils/hooks_tests.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { uiService } from "@web/core/ui/ui_service"; -import { useAutofocus, useBus, useListener, useService } from "@web/core/utils/hooks"; +import { useAutofocus, useBus, useChildRef, useForwardRefToParent, useListener, useService } from "@web/core/utils/hooks"; import { registry } from "@web/core/registry"; import { makeTestEnv } from "@web/../tests/helpers/mock_env"; import { @@ -423,5 +423,68 @@ QUnit.module("utils", () => { assert.rejects(comp.functionService.call("boundThis"), "Component is destroyed"); assert.strictEqual(nbCalls, 8); }); + + QUnit.module("useChildRef / useForwardRefToParent"); + + QUnit.test("simple usecase", async function (assert) { + let childRef; + let parentRef; + class Child extends Component { + setup() { + childRef = useForwardRefToParent("someRef"); + } + } + Child.template = xml`Hello`; + class Parent extends Component { + setup() { + this.someRef = useChildRef(); + parentRef = this.someRef; + } + } + Parent.template = xml`
`; + Parent.components = { Child }; + + const env = await makeTestEnv(); + const target = getFixture(); + + await mount(Parent, target, { env }); + assert.strictEqual(childRef.el, target.querySelector(".my_span")); + assert.strictEqual(parentRef.el, target.querySelector(".my_span")); + }); + + QUnit.test("useForwardRefToParent in a conditional child", async function (assert) { + class Child extends Component { + setup() { + useForwardRefToParent("someRef"); + } + } + Child.template = xml`Hello`; + class Parent extends Component { + setup() { + this.someRef = useChildRef(); + this.state = useState({ hasChild: true }); + } + } + Parent.template = xml`
`; + Parent.components = { Child }; + + const env = await makeTestEnv(); + const target = getFixture(); + + const parent = await mount(Parent, target, { env }); + assert.containsOnce(target, ".my_span"); + assert.strictEqual(parent.someRef.el, target.querySelector(".my_span")); + + parent.state.hasChild = false; + await nextTick(); + + assert.containsNone(target, ".my_span"); + assert.strictEqual(parent.someRef.el, null); + + parent.state.hasChild = true; + await nextTick(); + assert.containsOnce(target, ".my_span"); + assert.strictEqual(parent.someRef.el, target.querySelector(".my_span")); + }); }); });