From a62768a8a6837f1af458fa345cbf7e79adfb28fa Mon Sep 17 00:00:00 2001 From: Lucas Perais Date: Wed, 31 Aug 2022 09:33:35 +0000 Subject: [PATCH] [FIX] web: FormRenderer is responsible for focusing default field The FormView can autofocus a `default_field` if it exists, or, the first usable field. This commit moves the logic to the FormRenderer, has we need this feature in the KanbanRecordQuickCreate. Besides, it makes sense for the FormRenderer to have that responsibility. closes odoo/odoo#99297 Signed-off-by: Lucas Perais (lpe) --- .../static/src/views/form/form_controller.js | 21 +++---- .../static/src/views/form/form_renderer.js | 24 ++++++- .../static/tests/views/kanban_view_tests.js | 62 +++++++++++++++++++ 3 files changed, 94 insertions(+), 13 deletions(-) diff --git a/addons/web/static/src/views/form/form_controller.js b/addons/web/static/src/views/form/form_controller.js index ef202a5a4f6..43d93d16b84 100644 --- a/addons/web/static/src/views/form/form_controller.js +++ b/addons/web/static/src/views/form/form_controller.js @@ -215,23 +215,20 @@ export class FormController extends Component { this.env.config.setDisplayName(this.displayName()); }); - const { autofocusFieldId, disableAutofocus } = this.archInfo; + const { disableAutofocus } = this.archInfo; if (!disableAutofocus) { useEffect( (isInEdition) => { - let elementToFocus; - if (isInEdition) { - elementToFocus = - (autofocusFieldId && - rootRef.el.querySelector(`#${autofocusFieldId}`)) || - rootRef.el.querySelector(".o_content .o_field_widget input"); - } else { - elementToFocus = + if ( + !isInEdition && + !rootRef.el.querySelector(".o_content").contains(document.activeElement) + ) { + const elementToFocus = rootRef.el.querySelector(".o_content button.btn-primary") || rootRef.el.querySelector(".o_control_panel .o_form_button_edit"); - } - if (elementToFocus) { - elementToFocus.focus(); + if (elementToFocus) { + elementToFocus.focus(); + } } }, () => [this.model.root.isInEdition] diff --git a/addons/web/static/src/views/form/form_renderer.js b/addons/web/static/src/views/form/form_renderer.js index 3959a61db0d..9034eac12dc 100644 --- a/addons/web/static/src/views/form/form_renderer.js +++ b/addons/web/static/src/views/form/form_renderer.js @@ -16,7 +16,7 @@ import { FormCompiler } from "./form_compiler"; import { FormLabel } from "./form_label"; import { StatusBarButtons } from "./status_bar_buttons/status_bar_buttons"; -const { Component, onMounted, onWillUnmount, useSubEnv, useRef, useState, xml } = owl; +const { Component, onMounted, onWillUnmount, useEffect, useSubEnv, useRef, useState, xml } = owl; export class FormRenderer extends Component { setup() { @@ -38,6 +38,28 @@ export class FormRenderer extends Component { this.onResize = useDebounced(this.render, 200); onMounted(() => browser.addEventListener("resize", this.onResize)); onWillUnmount(() => browser.removeEventListener("resize", this.onResize)); + + const { autofocusFieldId, disableAutofocus } = archInfo; + if (!disableAutofocus) { + const rootRef = useRef("compiled_view_root"); + useEffect( + (isInEdition, rootEl) => { + if (!rootEl) { + return; + } + let elementToFocus; + if (isInEdition) { + elementToFocus = + (autofocusFieldId && rootEl.querySelector(`#${autofocusFieldId}`)) || + rootEl.querySelector(`.o_content .o_field_widget input`); + } + if (elementToFocus) { + elementToFocus.focus(); + } + }, + () => [this.props.record.isInEdition, rootRef.el] + ); + } } evalDomainFromRecord(record, expr) { diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index 614c0598648..b76ccc7ab5c 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -1399,6 +1399,68 @@ QUnit.module("Views", (hooks) => { ]); }); + QUnit.test( + "quick create record should focus default field [REQUIRE FOCUS]", + async function (assert) { + serverData.views["partner,some_view_ref,form"] = + "
" + + '' + + '' + + '' + + ""; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: + '' + + '' + + '' + + '
' + + "
", + groupBy: ["bar"], + }); + + await click(target, ".o-kanban-button-new"); + assert.strictEqual( + document.activeElement, + target.querySelector(".o_field_widget[name=int_field] input") + ); + } + ); + + QUnit.test( + "quick create record should focus first field input [REQUIRE FOCUS]", + async function (assert) { + serverData.views["partner,some_view_ref,form"] = + "
" + + '' + + '' + + '' + + ""; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: + '' + + '' + + '' + + '
' + + "
", + groupBy: ["bar"], + }); + + await click(target, ".o-kanban-button-new"); + assert.strictEqual( + document.activeElement, + target.querySelector(".o_field_widget[name=foo] input") + ); + } + ); + QUnit.test("quick_create_view without quick_create option", async (assert) => { serverData.views["partner,some_view_ref,form"] = `