[FIX] web: save an empty many2many_tags required
Before this commit, the required attribute has no effect on the x2many fields. It will always be valid unless one of its records is invalid. Problem: In some cases, we would like to be able to make some x2many fields required. For example, many2many_tags should be invalid if it contains no records. In legacy, if a field is required, then it has the responsibility to evaluate if its value is valid. To do this, each field contained the isSet function which returns true if the value is set. In our new architecture, it is the model that evaluates if the value of a field is valid based on the field type. It is therefore no longer possible to customise the evaluation of the validity of a field based on the FieldComponent. Solution: This commit will reintroduce the possibility to customize the evaluation of the validity of a field based on the FieldComponent. To do this, we add the possibility to define a static isSet function on the FieldComponent. If this function is present, it will be used to evaluate if the field value is set or not. closes odoo/odoo#98873 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: '<form><field name="timmy" widget="many2many_tags" required="1"/></form>',
|
||||
});
|
||||
|
||||
patchWithCleanup(form.env.services.notification, {
|
||||
add: (message, params) => {
|
||||
assert.strictEqual(message.toString(), "<ul><li>pokemon</li></ul>");
|
||||
assert.deepEqual(params, { title: "Invalid fields: ", type: "danger" });
|
||||
},
|
||||
});
|
||||
|
||||
await clickSave(target);
|
||||
assert.containsOnce(target, "[name='timmy'].o_field_invalid");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user