diff --git a/addons/web/static/src/views/basic_relational_model.js b/addons/web/static/src/views/basic_relational_model.js index 5f25eb4aacc..76620713b17 100644 --- a/addons/web/static/src/views/basic_relational_model.js +++ b/addons/web/static/src/views/basic_relational_model.js @@ -355,8 +355,8 @@ export class Record extends DataPoint { } for (const fieldName in this.activeFields) { const fieldType = this.fields[fieldName].type; + const activeField = this.activeFields[fieldName]; if (fieldName in this._requiredFields) { - const activeField = this.activeFields[fieldName]; if ( !evalDomain(this._requiredFields[fieldName], this.evalContext) || (activeField && activeField.alwaysInvisible) @@ -365,6 +365,15 @@ export class Record extends DataPoint { continue; } } + + const isSet = + activeField && activeField.FieldComponent && activeField.FieldComponent.isSet; + + if (this.isRequired(fieldName) && isSet && !isSet(this.data[fieldName])) { + this.setInvalidField(fieldName); + continue; + } + switch (fieldType) { case "boolean": case "float": @@ -383,7 +392,7 @@ export class Record extends DataPoint { } break; default: - if (this.isRequired(fieldName) && !this.data[fieldName]) { + if (!isSet && this.isRequired(fieldName) && !this.data[fieldName]) { this.setInvalidField(fieldName); } } diff --git a/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js b/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js index 8fab6d0daa4..c0585db16ec 100644 --- a/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js +++ b/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js @@ -304,6 +304,7 @@ Many2ManyTagsField.supportedTypes = ["many2many"]; Many2ManyTagsField.fieldsToFetch = { display_name: { name: "display_name", type: "char" }, }; +Many2ManyTagsField.isSet = (value) => value.count > 0; Many2ManyTagsField.extractProps = ({ attrs, field }) => { return { diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index ec01a45cd02..3503c325d45 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -579,6 +579,15 @@ export class Record extends DataPoint { this._removeInvalidFields([fieldName]); continue; } + + const isSet = + activeField && activeField.FieldComponent && activeField.FieldComponent.isSet; + + if (this.isRequired(fieldName) && isSet && !isSet(this.data[fieldName])) { + this.setInvalidField(fieldName); + continue; + } + switch (fieldType) { case "boolean": case "float": @@ -592,7 +601,7 @@ export class Record extends DataPoint { } break; default: - if (this.isRequired(fieldName) && !this.data[fieldName]) { + if (!isSet && this.isRequired(fieldName) && !this.data[fieldName]) { this.setInvalidField(fieldName); } } diff --git a/addons/web/static/tests/views/fields/many2many_tags_field_tests.js b/addons/web/static/tests/views/fields/many2many_tags_field_tests.js index f87166c1c26..defc1ff834e 100644 --- a/addons/web/static/tests/views/fields/many2many_tags_field_tests.js +++ b/addons/web/static/tests/views/fields/many2many_tags_field_tests.js @@ -1559,4 +1559,25 @@ QUnit.module("Fields", (hooks) => { "goldsilver" ); }); + + QUnit.test("save a record with an empty many2many_tags required", async function (assert) { + assert.expect(3); + + const form = await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: '
', + }); + + patchWithCleanup(form.env.services.notification, { + add: (message, params) => { + assert.strictEqual(message.toString(), ""); + assert.deepEqual(params, { title: "Invalid fields: ", type: "danger" }); + }, + }); + + await clickSave(target); + assert.containsOnce(target, "[name='timmy'].o_field_invalid"); + }); });