fix(magento-customer): honor Magento's required-status for the address telephone - #2663
Open
paales wants to merge 4 commits into
Open
fix(magento-customer): honor Magento's required-status for the address telephone#2663paales wants to merge 4 commits into
paales wants to merge 4 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: ce9f531 The changes in this PR will be included in the next version bump. This PR includes changesets to release 87 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
paales
commented
Aug 6, 2026
paales
commented
Aug 6, 2026
…s telephone `CartAddressInput.telephone` is a non-nullable `String!`, so the address forms always had to send a value. Because the mutation variable is declared as an optional `String`, `required.telephone` resolved to `false`, the field rendered as optional and `onBeforeSubmit` substituted a `000 - 000 0000` placeholder for an empty value — storing a fake phone number on the order. Magento does expose whether an address requires a telephone: `attributesForm(formCode: "customer_address_edit")` returns `is_required` per address attribute and reflects `customer/address/telephone_show`. - Add `useAddressAttributesRequired()` / `useTelephoneRequired()` to `@graphcommerce/magento-customer`, built on the existing `useAttributesForm` query, plus a shared `placeholderTelephone` constant. - `ShippingAddressForm`, `EditBillingAddressForm` and `EditAddressForm` mark the telephone field required when Magento says so, and submit an empty string instead of the placeholder when Magento says it is optional. The placeholder is only used while the metadata hasn't loaded, so shops that require a telephone keep working. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d it
Review feedback: drop the `useAddressAttributes` indirection.
- Remove `hooks/useAddressAttributes.ts` (`useAddressAttributesRequired`,
`useTelephoneRequired`, `placeholderTelephone`). Every address form now calls
`useAttributesForm({ formCode: 'customer_address_edit' })` itself and reads
`is_required` off the telephone attribute; the placeholder string is inline
again, matching how it was already written in the surrounding code.
- Preload the metadata in `getStaticProps` the same way the account pages
preload `customer_account_create` / `customer_account_edit`:
`if (magentoVersion >= 247) await preloadAttributesForm(client, 'customer_address_edit')`
on the checkout, checkout-address-edit, billing-address-edit and account
address-edit pages of all three examples. That also closes the window where a
customer could submit the form before the attribute metadata resolved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review feedback: the `000 - 000 0000` fallback only existed because the forms
couldn't tell whether the telephone was conditionally required. Now that they
read `is_required` from the address attribute metadata, it has no reason to
exist.
`ShippingAddressForm`, `EditBillingAddressForm` and `EditAddressForm` submit
`variables.telephone || ''` — an empty string satisfies the non-nullable
`CartAddressInput.telephone`, and Magento validates it against the very same
`is_required` the form renders with
(`Magento\Customer\Model\Address\Validator\General::checkOptionalFields` reads
`eavConfig->getAttribute('customer_address', 'telephone')->getIsRequired()`).
Behavior change: a customer who bypasses the client-side validation on a shop
that requires a telephone now gets `"telephone" is required. Enter and try
again.` instead of an order carrying a fake number. Verified against Magento
2.4.9 with `customer/address/telephone_show = req`.
The placeholder string survives only as a `legacyPlaceholderTelephone` constant
per form, used to clear it out of addresses that were saved with it before this
change so the customer is asked for a real number.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`attributesForm` — and with it any way to know whether a shop requires a telephone — only exists since Magento 2.4.7. Below that the placeholder flow is still the active behavior, so neither stripping a stored placeholder nor submitting an empty string is correct there. Both directions now live in one helper, `packages/magento-customer/utils/legacyPlaceholderTelephone.ts`: - `stripLegacyPlaceholderTelephone(telephone)` — clears a stored `000 - 000 0000` when loading an address into a form; returns the value untouched below 2.4.7. - `applyLegacyPlaceholderTelephone(telephone)` — submits an empty string for an empty field so Magento validates it; falls back to the placeholder below 2.4.7, where the form can never know the field is required. `ShippingAddressForm`, `EditBillingAddressForm` and `EditAddressForm` import the helper instead of each carrying a local constant. The required-status derivation needs no extra gate: below 2.4.7 `attributesForm` yields nothing, so `telephoneRequired` stays `undefined` and the field renders exactly as it did before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
paales
force-pushed
the
feature/address-telephone-required
branch
from
August 10, 2026 10:32
036e129 to
ce9f531
Compare
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.
Written by Claude Code:
The problem
CartAddressInput.telephoneis a non-nullableString!in Magento's schema, so the address forms always have to send something. The mutation variables however declare it as an optionalStringwith a placeholder default:handlerFactoryderivesrequiredfromvariable.type.kind === NON_NULL_TYPE, sorequired.telephoneresolves tofalse, the field renders as optional, andonBeforeSubmitfills the gap:Every checkout where the customer skipped the field therefore stores a fake phone number on the order — it shows up in the Magento admin, in order confirmation mails and in any address template that renders
telephone.Magento already tells us
attributesForm(formCode: "customer_address_edit")returnsis_requiredper address attribute, and it reflects thecustomer/address/telephone_showstore configuration (required / optional / hidden). Against a stock Magento 2.4.9:GraphCommerce already queries this —
useAttributesFormin@graphcommerce/magento-store— but only for the customer account create/edit forms. The address forms never looked at it.The change
ShippingAddressForm,EditBillingAddressFormandEditAddressFormeach call the hook directly:requiredwhen Magento says it is required.Magento\Customer\Model\Address\Validator\General::checkOptionalFields()checkseavConfig->getAttribute('customer_address', 'telephone')->getIsRequired(), andcustomer/address/telephone_showis what writes that flag (Show\AddressOnly:req→ 1,opt→ 0, hidden → 0).legacyPlaceholderTelephoneconstant, so a customer editing an address that still carries it gets an empty required field rather than a prefilled fake number. Nothing writes that string anymore.Behavior change
Where a customer who bypassed the client-side validation previously ended up with a successful order carrying
000 - 000 0000, a shop that requires a telephone now returns a proper validation error. Verified against Magento 2.4.9 withtelephone_show = req:telephonesent tosetShippingAddressesOnCart"""telephone" is required. Enter and try again."0612345678"That window is small — the preload below puts the metadata in the Apollo cache before first render — and failing loudly beats silently storing junk.
Version gate
attributesFormonly exists since Magento 2.4.7, so all of the above is gated in one helper,packages/magento-customer/utils/legacyPlaceholderTelephone.ts:stripLegacyPlaceholderTelephone(telephone)— clears a stored placeholder when an address is loaded into a form; returns the value untouched below 2.4.7.applyLegacyPlaceholderTelephone(telephone)— submits''for an empty field; falls back to the placeholder below 2.4.7.The required-status derivation needs no extra gate: below 2.4.7
attributesFormyields nothing, sotelephoneRequiredstaysundefinedand the field renders exactly as before. Net effect on < 2.4.7 is identical to today.CreateCustomerAddressFormneeds no change — its mutation declares$telephone: String!, so it was already required.Preloading
The metadata is preloaded in
getStaticProps, the same wayaccount/signin.tsxandaccount/name/index.tsxalready preloadcustomer_account_create/customer_account_edit:Applied to
checkout/index.tsx,checkout/edit/billing-address.tsx,checkout/customer/addresses/edit.tsxandaccount/addresses/edit.tsxin all three examples. Besides saving a client-side round trip, this closes the window where a customer could submit the form before the metadata resolved and still end up with the placeholder.Notes / deliberately out of scope
$telephone: String = "000 - 000 0000"defaults inSetShippingAddress.graphql,SetShippingBillingAddress.graphqlandSetBillingAddress.graphqlare left as-is. They are unreachable through the forms (useFormGqlalways sends the variable) and removing the default would break any consumer that calls the mutation directly without a telephone.telephoneis wired up. The same metadata can drivecompany/vat_id/postcoderequired-status later, butpostcodein particular is country-dependent in Magento (is_required = falsewhile the actual requirement comes from the zip-optional country list), so that deserves its own change.🤖 Generated with Claude Code