From 62f3eee09de16e479e36d74515469472f4e8222d Mon Sep 17 00:00:00 2001 From: Luca Fuser Date: Mon, 31 Aug 2026 20:14:00 +0200 Subject: [PATCH] fix: serialize the widget form the way a browser would Two blocks can render the same widget parameter. Magento\Widget\Block\Adminhtml\Widget\Options emits every parameter, including the ones declared visible="false", as a field carrying the widget.xml default; a module adding its own options block to the adminhtml_widget_loadoptions handle then renders some of those parameters again as visible fields under the same name. Prototype's accumulator concatenated duplicates, so parameters[loop] arrived as ['0','1']: selects were forced to their first allowed option and text parameters were imploded or dropped. It now follows the submit semantics of a form: a trailing [] makes a value a list, everything else is last one wins, unchecked checkboxes and radios are skipped rather than contributing their value attribute, and disabled, file, submit and button fields are left out. Reading the element directly instead of looking it up by id also stops fields without an id from being dropped. --- .../web/js/form/element/widget-builder.js | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/view/adminhtml/web/js/form/element/widget-builder.js b/view/adminhtml/web/js/form/element/widget-builder.js index ce2e20f..229a2d5 100644 --- a/view/adminhtml/web/js/form/element/widget-builder.js +++ b/view/adminhtml/web/js/form/element/widget-builder.js @@ -195,36 +195,37 @@ define([ }, serializeElements: function (elements) { - let options = {hash: true, submit: true}, - key, - value, - submitted = false, - submit = options.submit, - accumulator, - initial; - - if (options.hash) { - initial = {}; - accumulator = function (result, key, value) { - if (key in result) { - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key] = result[key].concat(value); - } else result[key] = value; - return result; - }; - } + let result = {}; - return elements.inject(initial, function (result, element) { - if (!element.disabled && element.name) { - key = element.name; - value = $('#' + $(element).attr('id')).val(); - if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - result = accumulator(result, key, value); - } + for (let i = 0; i < elements.length; i++) { + let element = elements[i], + value; + + if (element.disabled || !element.name || element.type === 'file' + || element.type === 'submit' || element.type === 'button' + ) { + continue; } - return result; - }); + if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) { + continue; + } + + value = $(element).val(); + + if (value === null || value === undefined) { + continue; + } + + if (/\[\]$/.test(element.name)) { + let listKey = element.name.slice(0, -2); + + result[listKey] = (result[listKey] || []).concat(value); + } else { + result[element.name] = value; + } + } + + return result; }, renderWidgetBuilder: function () {