From 366238e2d18ab5b9b8f3eddea3a33ffdaa8f3132 Mon Sep 17 00:00:00 2001 From: sylardiere Date: Mon, 20 Apr 2026 09:00:41 +0200 Subject: [PATCH 1/6] persist custom form field --- src/Form/OnePageCheckoutAddressForm.php | 10 ++++- views/js/opc-address-modal.js | 53 ++++++++++++++++++++++-- views/public/opc-address-modal.bundle.js | 2 +- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/Form/OnePageCheckoutAddressForm.php b/src/Form/OnePageCheckoutAddressForm.php index 0d501d7..ebe047b 100644 --- a/src/Form/OnePageCheckoutAddressForm.php +++ b/src/Form/OnePageCheckoutAddressForm.php @@ -38,9 +38,15 @@ public function fillFromRequest(array $requestParameters, string $prefix = ''): { $this->syncFormatterCountryFromRequest($requestParameters, $prefix); + if (!$this->formFields) { + $this->formFields = $this->formatter->getFormat(); + } + $params = []; - foreach ($this->getAllowedFieldNames() as $fieldName) { - $params[$fieldName] = $requestParameters[$prefix . $fieldName] ?? $requestParameters[$fieldName] ?? null; + foreach ($this->formFields as $key => $field) { + $fieldName = $field->getName(); + $params[$fieldName] = $requestParameters[$prefix . $fieldName] ?? $requestParameters[$fieldName] + ?? $requestParameters[$prefix . $key] ?? $requestParameters[$key] ?? null; } return $this->fillWith($params); diff --git a/views/js/opc-address-modal.js b/views/js/opc-address-modal.js index d10eea0..cf64efb 100644 --- a/views/js/opc-address-modal.js +++ b/views/js/opc-address-modal.js @@ -302,6 +302,8 @@ function syncBillingSectionConstraints($addressForm, useSameAddress) { } function resetModalFields($modal) { + const knownFields = new Set(ADDRESS_FIELDS); + ADDRESS_FIELDS.forEach((fieldName) => { if (fieldName === 'id_address') { getModalField($modal, fieldName).val(''); @@ -314,8 +316,26 @@ function resetModalFields($modal) { return; } - if ($field.is('select')) { - $field.val(''); + $field.val(''); + }); + + + $modal.find('input, select, textarea').each((_, field) => { + const $field = $(field); + const name = String($field.attr('name') || ''); + + if (!name || knownFields.has(name) || isServerManagedField(name)) { + return; + } + + const type = getFieldType($field); + + if (type === 'hidden' || NON_PRESERVABLE_FIELD_TYPES.has(type)) { + return; + } + + if (type === 'checkbox' || type === 'radio') { + $field.prop('checked', false); return; } @@ -402,7 +422,7 @@ function populateForm($modal, address) { return; } - ADDRESS_FIELDS.forEach((fieldName) => { + Object.keys(address).forEach((fieldName) => { const value = typeof address[fieldName] === 'undefined' ? '' : address[fieldName]; const $field = getModalField($modal, fieldName); @@ -415,6 +435,19 @@ function populateForm($modal, address) { } function getAddressFromTrigger($trigger) { + const jsonAttr = $trigger.attr('data-address'); + + if (typeof jsonAttr === 'string' && jsonAttr !== '') { + try { + const parsed = JSON.parse(jsonAttr); + + if (parsed && typeof parsed === 'object') { + return parsed; + } + } catch (e) { + } + } + const address = {}; ADDRESS_FIELDS.forEach((fieldName) => { @@ -838,9 +871,11 @@ function applyAddressListsResponse(response, options = {}) { $deliveryList.toggleClass('d-none', addressCount <= 0); $deliveryFields.toggleClass('d-none', addressCount > 0); + $deliveryFields.find('input, select, textarea').prop('disabled', addressCount > 0); $billingList.toggleClass('d-none', addressCount <= 1); $billingFields.toggleClass('d-none', addressCount > 1); + $billingFields.find('input, select, textarea').prop('disabled', addressCount > 1); syncAllSavedAddressItemStyles(); @@ -1123,8 +1158,19 @@ $(document).on('click', '.js-delete-address', (event) => { }); }); +function disableHiddenInlineAddressFields() { + [DELIVERY_FIELDS_SELECTOR, BILLING_FIELDS_SELECTOR].forEach((selector) => { + const $section = $(selector); + + if ($section.length && $section.hasClass('d-none')) { + $section.find('input, select, textarea').prop('disabled', true); + } + }); +} + $(function () { disableClosedModalFields(); + disableHiddenInlineAddressFields(); $(MODAL_SELECTOR).each((_, modal) => updateModalSaveState($(modal))); syncAllSavedAddressItemStyles(); retriggerCheckoutValidation(); @@ -1132,6 +1178,7 @@ $(function () { prestashop.on(OPC_EVENTS.updatedOpcAddressForm, () => { disableClosedModalFields(); + disableHiddenInlineAddressFields(); $(MODAL_SELECTOR).each((_, modal) => updateModalSaveState($(modal))); retriggerCheckoutValidation(); }); diff --git a/views/public/opc-address-modal.bundle.js b/views/public/opc-address-modal.bundle.js index da88340..0f009aa 100644 --- a/views/public/opc-address-modal.bundle.js +++ b/views/public/opc-address-modal.bundle.js @@ -1 +1 @@ -(()=>{"use strict";const e={opcCarrierSelected:"opcCarrierSelected",opcCarriersUpdated:"opcCarriersUpdated",opcCarriersFailed:"opcCarriersFailed",opcCarriersLoading:"opcCarriersLoading",opcPaymentMethodsLoading:"opcPaymentMethodsLoading",opcPaymentMethodsUpdated:"opcPaymentMethodsUpdated",opcPaymentMethodsFailed:"opcPaymentMethodsFailed",opcPaymentMethodSelected:"opcPaymentMethodSelected",opcGuestInitSuccess:"opcGuestInitSuccess",opcFinalSubmitStarted:"opcFinalSubmitStarted",opcFormValidated:"opcFormValidated",opcBillingSectionToggled:"opcBillingSectionToggled",opcSubmitFailed:"opcSubmitFailed",opcDeliveryAddressUpdated:"opcDeliveryAddressUpdated",opcBillingAddressUpdated:"opcBillingAddressUpdated",opcDeliveryAddressSelected:"opcDeliveryAddressSelected",opcBillingAddressSelected:"opcBillingAddressSelected",opcCartSummaryBeforeUpdate:"opcCartSummaryBeforeUpdate",opcCartSummaryUpdated:"opcCartSummaryUpdated",updatedOpcAddressForm:"updatedOpcAddressForm",opcCarriersRetry:"opcCarriersRetry",opcPaymentMethodsRetry:"opcPaymentMethodsRetry"};const t={opc:{checkout:".one-page-checkout",form:"#opc-form",payButton:"#opc-pay-button",payAmount:"#opc-pay-amount",addressesSection:".js-opc-addresses-section",deliveryMethods:"#opc-delivery-methods",paymentMethods:"#opc-payment-methods",deliverySection:"#opc-delivery-address",deliveryFields:"#opc-delivery-address-fields",billingSection:"#opc-billing-section",billingFields:"#opc-billing-address-fields",deliveryList:"#opc-delivery-address-content-list",billingList:"#opc-billing-address-content-list",useSameAddress:'[name="use_same_address"]',checkoutFooter:".one-page-checkout__footer",contactSection:".js-opc-contact-section",addressRadio:".js-opc-address-radio",addressItem:".opc-address-item",addressLabel:".form-check-label"},templates:{carrierLoader:"#opc-template-loader",carrierError:"#opc-template-carriers-error",paymentLoader:"#opc-template-payment-loader",paymentError:"#opc-template-payment-error"},inputs:{deliveryOption:'input[name="delivery_option"]',paymentOption:'input[name="payment-option"]',email:'input[name="email"]',conditions:'.one-page-checkout input[name^="conditions_to_approve["][required]'},modals:{address:"#opc-address-modal, #modal-delivery, #modal-invoice"}};function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}function n(e){var t=window&&"object"===r(window.ps_onepagecheckout)&&window.ps_onepagecheckout?window.ps_onepagecheckout:null;return t&&t.urls&&t.urls[e]?String(t.urls[e]):""}function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,i,d,a=[],s=!0,c=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;s=!1}else for(;!(s=(n=i.call(r)).done)&&(a.push(n.value),a.length!==t);s=!0);}catch(e){c=!0,o=e}finally{try{if(!s&&null!=r.return&&(d=r.return(),Object(d)!==d))return}finally{if(c)throw o}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?i(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r0}(e))||e.checkValidity())}function K(e){var t=e.find(s);if(t.length)if(e.get(0)instanceof HTMLElement&&e.hasClass("show")){var r=e.find("input, select, textarea").toArray().every(function(e){return Q(e)});t.prop("disabled",!r)}else t.prop("disabled",!0)}function W(e,t,n){var o=function(e){return{$wrapper:e.find(".state-field-wrapper, #state-field-wrapper").first(),$select:e.find('[name="id_state"], [name$="id_state"]').first(),$row:e.find(".address-country-row, #address-country-row").first()}}(e),i=o.$wrapper,d=o.$select,a=o.$row;if(i.length&&d.length){var s=t&&Array.isArray(t.states)?t.states:[];if(!(Boolean(t&&t.hasStates)||s.length>0))return i.hide(),d.prop("required",!1).val(""),void(a.length&&a.removeClass("form-fields-row--3").addClass("form-fields-row--2"));var c=String(d.attr("data-select-placeholder")||"");d.empty(),d.append(r("