[FIX] website: prevent circular dependency of duplicated fields
Steps to reproduce the bug: - Drop a "Form" snippet on the website. - Add three fields and rename them by "a", "b" and "b". - Change the conditional visibility of the first "b" and make it depend on "a". - Change the conditional visibility of "a" and make it depend on "b". - Save. -> Traceback "Maximum call stack exceeded" appears. A field with a conditional visibility is visible if at at least one field with the dependency name is visible. The problem is that in our case, it exists a circular dependency between "a" and one of the "b" leading to an infinite loop during this check. Before this commit all the fields of the form were checked and all the labels of the fields that do not create a circular dependency were proposed in the file visibility selector. The problem is that in our case, one of the "b" field does not create a circular dependency while the other does. To solve the problem, the `_recursiveFindCircular()` function has been adapted in order to not propose a label that would create a circular dependency in the file visibility selector. task-3291044 X-original-commit: f010b128be29e884c89dd58f1c575a163e229d5b Part-of: odoo/odoo#140928
This commit is contained in:
@@ -266,11 +266,12 @@ const FieldEditor = FormEditor.extend({
|
||||
* Returns the name of the field
|
||||
*
|
||||
* @private
|
||||
* @param {HTMLElement} fieldEl
|
||||
* @returns {string}
|
||||
*/
|
||||
_getFieldName: function () {
|
||||
const multipleName = this.$target[0].querySelector('.s_website_form_multiple');
|
||||
return multipleName ? multipleName.dataset.name : this.$target[0].querySelector('.s_website_form_input').name;
|
||||
_getFieldName: function (fieldEl = this.$target[0]) {
|
||||
const multipleName = fieldEl.querySelector('.s_website_form_multiple');
|
||||
return multipleName ? multipleName.dataset.name : fieldEl.querySelector('.s_website_form_input').name;
|
||||
},
|
||||
/**
|
||||
* Returns the type of the field, can be used for both custom and existing fields
|
||||
@@ -1277,14 +1278,26 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
*/
|
||||
_renderCustomXML: async function (uiFragment) {
|
||||
const recursiveFindCircular = (el) => {
|
||||
if (el.dataset.visibilityDependency === this._getFieldName()) {
|
||||
return true;
|
||||
const dependentFieldName = this._getFieldName(el);
|
||||
// Get all the fields that have the same label as the dependent
|
||||
// field.
|
||||
let dependentFieldEls = Array.from(this.formEl
|
||||
.querySelectorAll(`.s_website_form_input[name="${dependentFieldName}"]`))
|
||||
.map((el) => el.closest(".s_website_form_field"));
|
||||
// Remove the duplicated fields. This could happen if the field has
|
||||
// multiple inputs ("Multiple Checkboxes" for example.)
|
||||
dependentFieldEls = new Set(dependentFieldEls);
|
||||
const fieldName = this._getFieldName();
|
||||
for (const dependentFieldEl of dependentFieldEls) {
|
||||
if (dependentFieldEl.dataset.visibilityDependency === fieldName) {
|
||||
return true;
|
||||
}
|
||||
const dependencyInputEl = this._getDependencyEl(dependentFieldEl);
|
||||
if (dependencyInputEl && recursiveFindCircular(dependencyInputEl.closest(".s_website_form_field"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const dependencyInputEl = this._getDependencyEl(el);
|
||||
if (!dependencyInputEl) {
|
||||
return false;
|
||||
}
|
||||
return recursiveFindCircular(dependencyInputEl.closest('.s_website_form_field'));
|
||||
return false;
|
||||
};
|
||||
|
||||
// Update available visibility dependencies
|
||||
|
||||
@@ -182,6 +182,18 @@
|
||||
content: 'Change the label position of the phone field',
|
||||
trigger: 'we-button[data-select-label-position="right"]',
|
||||
},
|
||||
...addCustomField("char", "text", "Conditional Visibility Check 1", false),
|
||||
...addCustomField("char", "text", "Conditional Visibility Check 2", false),
|
||||
...selectButtonByData("data-set-visibility='conditional'"),
|
||||
...selectButtonByData("data-set-visibility-dependency='Conditional Visibility Check 1'"),
|
||||
...addCustomField("char", "text", "Conditional Visibility Check 2", false),
|
||||
...selectFieldByLabel("Conditional Visibility Check 1"),
|
||||
...selectButtonByData("data-set-visibility='conditional'"),
|
||||
{
|
||||
content: "Check that 'Conditional Visibility Check 2' is not in the list of the visibility selector of Conditional Visibility Check 1",
|
||||
trigger: "we-select[data-name='hidden_condition_opt']:not(:has(we-button[data-set-visibility-dependency='Conditional Visibility Check 2']))",
|
||||
run: () => null,
|
||||
},
|
||||
...addExistingField('email_cc', 'text', 'Test conditional visibility', false, {visibility: CONDITIONALVISIBILITY, condition: 'odoo'}),
|
||||
|
||||
...addExistingField('date', 'text', 'Test Date', true),
|
||||
|
||||
Reference in New Issue
Block a user