Skip to content

Stop nesting form elements in the checkout address step - #233

Draft
boo-code wants to merge 1 commit into
PrestaShop:developfrom
boo-code:fix/checkout-address-form-nesting-36563
Draft

Stop nesting form elements in the checkout address step#233
boo-code wants to merge 1 commit into
PrestaShop:developfrom
boo-code:fix/checkout-address-form-nesting-36563

Conversation

@boo-code

@boo-code boo-code commented Sep 5, 2026

Copy link
Copy Markdown
Contributor
Questions Answers
Description? The checkout address step opens a <form> around the whole block and then renders full address <form> elements inside it, and checkout/_partials/address-form.tpl opens a third <form> around the Continue button. HTML forbids nesting, and the parser resolves it by ignoring the inner start tag and letting the inner </form> close the OUTER form - so every control rendered after an address form loses its form owner. This attaches the step's own controls (address selector radios, Continue button, not-valid-addresses) to the step form through the form attribute, leaves that form element empty so the address forms are siblings rather than children, and replaces the buttons-block <form> with a <div>, which is what hummingbird already does.
Type? bug fix
BC breaks? no
Deprecations? no
Fixed ticket? PrestaShop/PrestaShop#36563
Sponsor company -
How to test? On a 9.2 shop with this theme active: reach checkout with two saved addresses, click "Billing address differs from shipping address", then "Edit" on the delivery address. Before this change the Continue button, both invoice radios and #not-valid-addresses have no form owner (document.querySelector('button[name=confirm-addresses]').form is null), so Continue does nothing. After, all three belong to the step form.

Measured on 9.2.0 with classic 3.1.2, counting <form> tags in the address step of the served HTML and reading form ownership from the parsed DOM:

state                                        before          after
2 addresses, editAddress=delivery      10 tags depth 2   10 tags depth 1
1 address,   editAddress=delivery      16 tags depth 3   12 tags depth 1

Depth 3 is the case in the issue's screenshot: step form, then the address form, then the buttons-block form.

Form ownership in the two-address state, before -> after:

button[name=confirm-addresses]   null -> the step form
input[name=id_address_invoice]   null -> the step form   (both radios)
#not-valid-addresses             null -> the step form

Why the form attribute rather than moving the markup

The step form is needed for the address selectors and the Continue button; the address form is needed for
the address fields. They are never the same submission, but they interleave: a delivery selector can be
followed by an invoice form, so no arrangement of open/close tags puts every selector in the same form as
the Continue button. Explicit form ownership is the platform feature for exactly that, and it keeps source
order, markup and CSS unchanged.

Companion

PrestaShop/hummingbird needs the same change (branch fix/checkout-address-form-nesting-36563); its
address-form.tpl already uses a <div> for the buttons block, so only the step-form half applies there,
plus a one-line fix to initFormValidation which looked the submit button up with querySelector and so
only saw DOM descendants.

The address step wrapped the whole block in a <form> and rendered full address
<form> elements inside it, and the address form's own buttons block opened yet
another <form> around the Continue button. The HTML parser resolves nesting by
dropping the inner start tag and letting the inner </form> close the outer form,
so every control after the address form loses its form owner. Measured on 9.2.0
with classic 3.1.2: with two saved addresses, a separate invoice address and the
delivery address open for editing, the Continue button, both invoice radios and
the not-valid-addresses input all report form === null.

Attach those controls to the step form through the form attribute instead, leave
the step form element empty so the address forms stay siblings, and replace the
buttons-block form with a div, matching what hummingbird already does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant