From 3ef8083dcb10e5d5950a3ef26049b474db03d385 Mon Sep 17 00:00:00 2001 From: "Michael (mcm)" Date: Thu, 28 Oct 2021 12:49:01 +0000 Subject: [PATCH] [FIX] web: autofocus conditional element Before this commit, useAutofocus hook used the effect dependency to check if the target is in dom but this dependency is computed in onWillPatch and can be outdated when checking it in onPatched. Now, the target isn't a dependency anymore and is computed just before the check. Part-of: odoo/odoo#76472 --- addons/web/static/src/core/utils/hooks.js | 5 +- .../static/tests/core/utils/hooks_tests.js | 70 ++++++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/core/utils/hooks.js b/addons/web/static/src/core/utils/hooks.js index c870d5e8659..809ee0fd3e9 100644 --- a/addons/web/static/src/core/utils/hooks.js +++ b/addons/web/static/src/core/utils/hooks.js @@ -42,7 +42,8 @@ export function useAutofocus(params = {}) { const selector = params.selector || "[autofocus]"; let forceFocusCount = 0; useEffect( - function autofocus(target) { + function autofocus() { + const target = comp.el.querySelector(selector); if (target) { target.focus(); if (["INPUT", "TEXTAREA"].includes(target.tagName)) { @@ -51,7 +52,7 @@ export function useAutofocus(params = {}) { } } }, - () => [comp.el.querySelector(selector), forceFocusCount] + () => [forceFocusCount] ); return function focusOnUpdate() { diff --git a/addons/web/static/tests/core/utils/hooks_tests.js b/addons/web/static/tests/core/utils/hooks_tests.js index 632b35ed537..93fbef14ddd 100644 --- a/addons/web/static/tests/core/utils/hooks_tests.js +++ b/addons/web/static/tests/core/utils/hooks_tests.js @@ -1,6 +1,7 @@ /** @odoo-module **/ -import { useBus, useEffect, useListener, useService } from "@web/core/utils/hooks"; +import { uiService } from "@web/core/ui/ui_service"; +import { useAutofocus, useBus, useEffect, useListener, useService } from "@web/core/utils/hooks"; import { registry } from "@web/core/registry"; import { makeTestEnv } from "../../helpers/mock_env"; import { click, getFixture, nextTick } from "../../helpers/utils"; @@ -11,6 +12,73 @@ const serviceRegistry = registry.category("services"); QUnit.module("utils", () => { QUnit.module("Hooks", () => { + QUnit.module("useAutofocus"); + + QUnit.test("useAutofocus: simple usecase", async function (assert) { + class MyComponent extends Component { + setup() { + useAutofocus(); + } + } + MyComponent.template = tags.xml` + + + + `; + + registry.category("services").add("ui", uiService); + + const env = await makeTestEnv(); + const target = getFixture(); + const comp = await mount(MyComponent, { env, target }); + await nextTick(); + + assert.strictEqual(document.activeElement, comp.el.querySelector("input")); + + comp.render(); + await nextTick(); + assert.strictEqual(document.activeElement, comp.el.querySelector("input")); + + comp.destroy(); + }); + + QUnit.test("useAutofocus: conditional autofocus", async function (assert) { + class MyComponent extends Component { + setup() { + this.forceFocus = useAutofocus(); + this.showInput = true; + } + } + MyComponent.template = tags.xml` + + + + `; + + registry.category("services").add("ui", uiService); + + const env = await makeTestEnv(); + const target = getFixture(); + const comp = await mount(MyComponent, { env, target }); + await nextTick(); + + assert.strictEqual(document.activeElement, comp.el.querySelector("input")); + + comp.showInput = false; + comp.forceFocus(); + comp.render(); + await nextTick(); + assert.notStrictEqual(document.activeElement, comp.el.querySelector("input")); + + comp.showInput = true; + comp.forceFocus(); + comp.render(); + await nextTick(); + assert.strictEqual(document.activeElement, comp.el.querySelector("input")); + + comp.destroy(); + }); + QUnit.module("useBus"); QUnit.test("useBus hook: simple usecase", async function (assert) {