Stop nesting form elements in the checkout address step - #1099
Draft
boo-code wants to merge 1 commit into
Draft
Conversation
The address step wrapped the whole block in a <form>, and rendered full address <form> elements inside it. The HTML parser resolves that 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 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, and leave the form element itself empty so the address forms stay siblings. Form validation now looks the submit button up in form.elements, which covers both DOM containment and the form attribute.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
<form>around the whole block and then renders full address<form>elements inside it. 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 theformattribute and leaves that form element empty so the address forms are siblings rather than children.initFormValidationlooked its submit button up withquerySelector, which only sees DOM descendants, so it now searchesform.elements, which covers both containment and theformattribute.#not-valid-addresseshave no form owner (document.querySelector('button[name=confirm-addresses]').formisnull), so Continue does nothing. After, all three belong to the step form.Measured on 9.2.0 with this theme active, counting
<form>tags in the address step of the served HTML andreading form ownership from the parsed DOM:
Form ownership in the two-address state, before -> after:
Tests
src/js/form-validation.test.ts- 3 cases: a submit button nested in the form, a submit button attachedthrough the
formattribute, and a form with no submit button. Reverting onlysrc/js/form-validation.tsfails exactly the second one. Full jest suite 42/42, eslint clean.
Why the
formattribute rather than moving the markupThe 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/classic-themeneeds the same change (branchfix/checkout-address-form-nesting-36563, basedevelop), plus replacing the extra<form>itscheckout/_partials/address-form.tplopens around theContinue button with a
<div>- hummingbird already does that.