[FIX] web: FormStatusIndicator flickering

Purpose:
--------
Before this commit, if you edit a char field with an onchange in
an x2many, the FormStatusIndicator buttons will flicker.

How to reproduce:
-----------------
- Go to a form view with an x2many field in list mode
- Type a char in the char field of a record
- The FormStatusIndicator buttons are visible
- Click outside the char field
- An onchange is triggered

Before this commit:
    The FormStatusIndicator buttons will disappear until the onchange returns.

After this commit:
    The FormStatusIndicator buttons remain visible.

closes odoo/odoo#140179

Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
This commit is contained in:
FrancoisGe
2023-10-30 13:56:01 +00:00
parent c9ebb4de41
commit 64037d03d0
2 changed files with 60 additions and 9 deletions
@@ -53,7 +53,7 @@ export function useInputField(params) {
* On blur, we consider the field no longer dirty, even if it were to be invalid.
* However, if the field is invalid, the new value will not be committed to the model.
*/
function onChange(ev) {
async function onChange(ev) {
if (isDirty) {
isDirty = false;
let isInvalid = false;
@@ -69,15 +69,12 @@ export function useInputField(params) {
if (!isInvalid) {
pendingUpdate = true;
Promise.resolve(
component.props.record.update({ [component.props.name]: val })
).then(() => {
pendingUpdate = false;
});
lastSetValue = ev.target.value;
}
lastSetValue = inputRef.el.value;
component.props.record.model.bus.trigger("FIELD_IS_DIRTY", isDirty);
await component.props.record.update({ [component.props.name]: val });
pendingUpdate = false;
component.props.record.model.bus.trigger("FIELD_IS_DIRTY", isDirty);
}
}
}
function onKeydown(ev) {
@@ -1110,4 +1110,58 @@ QUnit.module("Fields", (hooks) => {
assert.containsNone(target, "[name='display_name'] input");
}
);
QUnit.test(
"edit a char field should display the status indicator buttons without flickering",
async function (assert) {
serverData.models.partner.records[0].p = [2];
serverData.models.partner.onchanges = {
foo() {},
};
const def = makeDeferred();
await makeView({
type: "form",
resModel: "partner",
serverData,
resId: 1,
arch: `
<form>
<field name="p">
<tree editable="bottom">
<field name="foo"/>
</tree>
</field>
</form>`,
async mockRPC(route, { method }) {
if (method === "onchange") {
assert.step("onchange");
await def;
}
},
});
assert.containsOnce(
target,
".o_form_status_indicator_buttons.invisible",
"form view is not dirty"
);
await click(target, ".o_data_cell");
await editInput(target, "[name='foo'] input", "a");
assert.verifySteps(["onchange"]);
assert.containsOnce(
target,
".o_form_status_indicator_buttons:not(.invisible)",
"form view is dirty"
);
def.resolve();
await nextTick();
assert.containsOnce(
target,
".o_form_status_indicator_buttons:not(.invisible)",
"form view is dirty"
);
}
);
});