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 59c0ca60a38..e4574968eb7 100644 --- a/addons/web/static/src/views/fields/input_field_hook.js +++ b/addons/web/static/src/views/fields/input_field_hook.js @@ -27,11 +27,6 @@ export function useInputField(params) { */ let isDirty = false; - /** - * A field is invalid if the parsing of its value failed. - */ - let isInvalid = false; - /** * The last value that has been commited to the model. * Not changed in case of invalid field value. @@ -55,7 +50,7 @@ export function useInputField(params) { function onChange(ev) { if (isDirty) { isDirty = false; - isInvalid = false; + let isInvalid = false; let val = ev.target.value; if (params.parse) { try { @@ -101,11 +96,12 @@ export function useInputField(params) { /** * Sometimes, a patch can happen with possible a new value for the field - * If the user was typing a new value (isDirty) or had enter an invalid value (isInvalid), + * If the user was typing a new value (isDirty) or the field is still invalid, * we need to do nothing. * If it is not such a case, we update the field with the new value. */ useEffect(() => { + const isInvalid = component.props.record.isInvalid(component.props.name); if (inputRef.el && !isDirty && !isInvalid) { inputRef.el.value = params.getValue(); lastSetValue = inputRef.el.value; @@ -125,13 +121,9 @@ export function useInputField(params) { return; } - if (isInvalid && !isDirty) { - return; - } - isDirty = inputRef.el.value !== lastSetValue; if (isDirty || urgent) { - isInvalid = false; + let isInvalid = false; isDirty = false; let val = inputRef.el.value; if (params.parse) { diff --git a/addons/web/static/tests/views/form/form_view_tests.js b/addons/web/static/tests/views/form/form_view_tests.js index e79115f7a6a..b04f35f398e 100644 --- a/addons/web/static/tests/views/form/form_view_tests.js +++ b/addons/web/static/tests/views/form/form_view_tests.js @@ -4229,6 +4229,31 @@ QUnit.module("Views", (hooks) => { assert.containsNone(document.body, ".modal", "there should not be a confirm modal"); }); + QUnit.test("discard invalid value", async function (assert) { + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: '
', + resId: 1, + }); + + await editInput(target, ".o_field_widget[name=int_field] input", "tralala"); + await click(target, ".o_form_view"); + assert.containsOnce(target, ".o_field_invalid"); + assert.strictEqual( + target.querySelector(".o_field_widget[name=int_field] input").value, + "tralala" + ); + + await clickDiscard(target); + assert.containsNone(target, ".o_field_invalid"); + assert.strictEqual( + target.querySelector(".o_field_widget[name=int_field] input").value, + "10" + ); + }); + QUnit.test("Domain: allow empty domain on fieldInfo", async function (assert) { assert.expect(1); serverData.models.partner.fields.product_id.domain = "[('display_name', '=', name)]";