[FIX] web: discard invalid input field

Before this commit, in a form view, discarding a record with an invalid
field containing an input does not restore the original value.

How to reproduce
- go to a form view with an integer field
- edit the integer field with an invalid value ("blabla")
- click outside the field (the field is displayed as invalid)
- click on the discard button

Before this commit:
The integer field always displays the invalid value.

After this commit:
The integer field displays the value before the edit.

closes odoo/odoo#101316

X-original-commit: f81e4019ca00953d9624557c98033aef46efc47a
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2022-09-27 17:11:53 +02:00
parent 04892cc17e
commit cb022c00a3
2 changed files with 29 additions and 12 deletions
@@ -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) {
@@ -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: '<form><field name="int_field"></field></form>',
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)]";