diff --git a/addons/web/static/src/views/fields/input_field_hook.js b/addons/web/static/src/views/fields/input_field_hook.js index b44054d60e7..8f39485ac17 100644 --- a/addons/web/static/src/views/fields/input_field_hook.js +++ b/addons/web/static/src/views/fields/input_field_hook.js @@ -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) { diff --git a/addons/web/static/tests/views/fields/char_field_tests.js b/addons/web/static/tests/views/fields/char_field_tests.js index 79eeee289b6..cd0346cccc6 100644 --- a/addons/web/static/tests/views/fields/char_field_tests.js +++ b/addons/web/static/tests/views/fields/char_field_tests.js @@ -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: ` +
+ + + + + +
`, + 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" + ); + } + ); });