[FIX] website_form: prevent input ids from being duplicated
When cloning a website_form field, we rerender the cloned field to reassign its elements ids and for attributes with a unique ID instead of the old ones. Rerendering the list also removes an issue with Selection fields that were not visible after a clone and a save, as it was usually done after a _rerenderXML, not executed after a clone. Also, _renderField docstring was wrong, and its return values terminology have been replaced with correct one. task-2485093 X-original-commit: 92bacc8907fa9577805b28a11894e7a006b2a5bf Part-of: odoo/odoo#75908
This commit is contained in:
committed by
Younn Olivier
parent
fc67a3370a
commit
151d570933
@@ -53,6 +53,15 @@ const FormEditor = options.Class.extend({
|
||||
}
|
||||
return field.records;
|
||||
},
|
||||
/**
|
||||
* Generates a new ID.
|
||||
*
|
||||
* @private
|
||||
* @returns {string} The new ID
|
||||
*/
|
||||
_generateUniqueID() {
|
||||
return Math.random().toString(36).substring(2, 15);
|
||||
},
|
||||
/**
|
||||
* Returns a field object
|
||||
*
|
||||
@@ -120,15 +129,18 @@ const FormEditor = options.Class.extend({
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} field
|
||||
* @returns {Promise<HTMLElement>}
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
_renderField: function (field) {
|
||||
field.id = Math.random().toString(36).substring(2, 15); // Big unique ID
|
||||
_renderField: function (field, resetId = false) {
|
||||
if (!field.id) {
|
||||
field.id = this._generateUniqueID();
|
||||
}
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = qweb.render("website.form_field_" + field.type, {field: field}).trim();
|
||||
if (field.description && field.description !== true) {
|
||||
$(template.content.querySelector('.s_website_form_field_description')).replaceWith(field.description);
|
||||
}
|
||||
template.content.querySelectorAll('input.datetimepicker-input').forEach(el => el.value = field.propertyValue);
|
||||
return template.content.firstElementChild;
|
||||
},
|
||||
});
|
||||
@@ -415,10 +427,10 @@ options.registry.WebsiteFormEditor = FormEditor.extend({
|
||||
field.formatInfo.requiredMark = this._isRequiredMark();
|
||||
field.formatInfo.optionalMark = this._isOptionalMark();
|
||||
field.formatInfo.mark = this._getMark();
|
||||
const htmlField = this._renderField(field);
|
||||
data.$target.after(htmlField);
|
||||
const fieldEl = this._renderField(field);
|
||||
data.$target.after(fieldEl);
|
||||
this.trigger_up('activate_snippet', {
|
||||
$snippet: $(htmlField),
|
||||
$snippet: $(fieldEl),
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -799,6 +811,17 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
// We need to reload the existing type list.
|
||||
this.rerender = true;
|
||||
},
|
||||
/**
|
||||
* Rerenders the clone to avoid id duplicates.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
onClone() {
|
||||
const field = this._getActiveField();
|
||||
delete field.id;
|
||||
const fieldEl = this._renderField(field);
|
||||
this._replaceFieldElement(fieldEl);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Options
|
||||
@@ -1013,7 +1036,7 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
uiFragment.appendChild(list);
|
||||
},
|
||||
/**
|
||||
* Replace the target content with the field provided
|
||||
* Replaces the target content with the field provided.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} field
|
||||
@@ -1025,12 +1048,20 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
if (activeField.type !== field.type) {
|
||||
field.value = '';
|
||||
}
|
||||
const htmlField = this._renderField(field);
|
||||
const fieldEl = this._renderField(field);
|
||||
this._replaceFieldElement(fieldEl);
|
||||
},
|
||||
/**
|
||||
* Replaces the target with provided field.
|
||||
*
|
||||
* @private
|
||||
* @param {HTMLElement} fieldEl
|
||||
*/
|
||||
_replaceFieldElement(fieldEl) {
|
||||
[...this.$target[0].childNodes].forEach(node => node.remove());
|
||||
[...htmlField.childNodes].forEach(node => this.$target[0].appendChild(node));
|
||||
[...htmlField.attributes].forEach(el => this.$target[0].removeAttribute(el.nodeName));
|
||||
[...htmlField.attributes].forEach(el => this.$target[0].setAttribute(el.nodeName, el.nodeValue));
|
||||
this.$target[0].querySelectorAll('input.datetimepicker-input').forEach(el => el.value = field.propertyValue);
|
||||
[...fieldEl.childNodes].forEach(node => this.$target[0].appendChild(node));
|
||||
[...fieldEl.attributes].forEach(el => this.$target[0].removeAttribute(el.nodeName));
|
||||
[...fieldEl.attributes].forEach(el => this.$target[0].setAttribute(el.nodeName, el.nodeValue));
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -1080,10 +1111,10 @@ options.registry.AddFieldForm = FormEditor.extend({
|
||||
addField: async function (previewMode, value, params) {
|
||||
const field = this._getCustomField('char', 'Custom Text');
|
||||
field.formatInfo = this._getDefaultFormat();
|
||||
const htmlField = this._renderField(field);
|
||||
this.$target.find('.s_website_form_submit, .s_website_form_recaptcha').first().before(htmlField);
|
||||
const fieldEl = this._renderField(field);
|
||||
this.$target.find('.s_website_form_submit, .s_website_form_recaptcha').first().before(fieldEl);
|
||||
this.trigger_up('activate_snippet', {
|
||||
$snippet: $(htmlField),
|
||||
$snippet: $(fieldEl),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user