[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) <lpe@odoo.com>
This commit is contained in:
Lucas Perais
2022-09-01 15:33:08 +02:00
parent e8ef723a89
commit a62768a8a6
3 changed files with 94 additions and 13 deletions
@@ -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]
@@ -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) {
@@ -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"] =
"<form>" +
'<field name="foo"/>' +
'<field name="int_field" default_focus="1"/>' +
'<field name="state" widget="priority"/>' +
"</form>";
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch:
'<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
'<field name="bar"/>' +
'<templates><t t-name="kanban-box">' +
'<div><field name="foo"/></div>' +
"</t></templates></kanban>",
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"] =
"<form>" +
'<field name="foo"/>' +
'<field name="int_field"/>' +
'<field name="state" widget="priority"/>' +
"</form>";
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch:
'<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
'<field name="bar"/>' +
'<templates><t t-name="kanban-box">' +
'<div><field name="foo"/></div>' +
"</t></templates></kanban>",
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"] = `
<form>