# Checkout Fields and Validation

> Checkout address schema, field rendering, local validation, terms, notices, and Store API submission.

<!-- Sources: src/Woo/CheckoutFieldSchema.php; src/Components/Woo/Shared/AddressFormProperties.php; src/Components/Woo/Shared/AddressFormMarkup.php; src/Components/Woo/BillingAddressForm/BillingAddressForm.php; src/Components/Woo/ShippingAddressForm/ShippingAddressForm.php; client/src/domains/woo/checkout-field-schema.ts; client/src/domains/woo/checkout-validation.ts; client/src/domains/woo/components/address-fields.ts; client/src/domains/woo/components/checkout-form.ts; client/src/domains/woo/store-api-client.ts; tests/e2e/components/woo/behavior.spec.ts -->

# Checkout Fields and Validation

Billing and shipping address forms are authored components, but their field rules come from WooCommerce.

## Field Schema

`CheckoutFieldSchema::build()` produces:

| Schema key | Meaning |
| --- | --- |
| `billing.countries` | Allowed billing countries. |
| `shipping.countries` | Allowed shipping countries. |
| `billing.fields` | Woo billing field rules normalized without the `billing_` prefix. |
| `shipping.fields` | Woo shipping field rules normalized without the `shipping_` prefix. |
| `locales` | Country-specific label, required, hidden, type, validation, priority, and autocomplete overrides. |
| `states` | State/province options by country. |
| `defaults` | Base billing country/state and shipping defaults. |

The runtime normalizes this schema before applying it, so missing or malformed schema data becomes empty field lists rather than runtime crashes.

## Address Form Props

Both address forms use the shared address property builder.

| Prop group | Meaning |
| --- | --- |
| `content.legend` and `content.show_legend` | Fieldset legend text and visibility. |
| Per-field `use_woo_defaults` | When true, Woo field copy and validation copy win. |
| Per-field custom copy | Label, field hint text, and local validation message used only when Woo defaults are disabled. |
| `accessibility.aria_label` | Accessible name for the fieldset. |
| `preview.state` | Builder preview state for fields. |

Billing fields include first name, last name, company, address lines, city, state, postcode, country, email, and phone. Shipping fields include the same address fields except email and phone.

## Country and State Controls

Country and state are UIChoice-backed controls with hidden transport inputs. Runtime behavior:

1. Render country options from the schema.
2. Select a default from the current value or Woo defaults.
3. Render state as a select when the selected country has predefined states.
4. Render state as a text input when the country requires free text.
5. Hide state when Woo marks it hidden.
6. Re-apply field labels, priorities, hidden flags, required flags, input types, and autocomplete tokens after country changes.

E2E covers changing billing country from `US` to `PL` and verifies that state switches from ready to hidden with an empty value.

## Different Shipping Address

`ShippingAddressForm` includes a different-shipping toggle. Runtime hides or shows the shipping fields based on that checkbox.

Checkout serialization follows the toggle:

| Toggle state | Payload behavior |
| --- | --- |
| Unchecked | Billing address is copied to shipping. |
| Checked | Rendered shipping fields are serialized separately. |

## Local Validation

`CheckoutForm` validates rendered fields before sending Store API requests.

| Validation | Behavior |
| --- | --- |
| Required fields | Checked on submit; required checks can be overridden by rendered `data-ome-required`. |
| Email | Billing email must match the local email pattern. |
| Country | Country value must exist in schema options. |
| State | State value must exist when the selected country has predefined states. |
| Hidden fields | Hidden Woo fields are not validated. |
| Rendered field scope | Only fields present in the authored checkout scope are validated. |

On local validation failure, no Store API checkout request is sent. E2E verifies invalid email blocks before `/wc/store/v1/checkout`.

## Store API Field Errors

If Woo returns checkout errors, the runtime maps them to fields when possible:

- It reads `data.params` field keys from Store API errors.
- It falls back to known Woo error codes such as missing email, first name, last name, address, country, postcode, phone, city, and state.
- It marks matching inputs with `aria-invalid`, updates field error text, and links fields to error messages with `aria-describedby`.

## Terms and Notices

`TermsCheckbox` tells the checkout store whether terms are required and accepted. If required terms are unchecked, the checkout store emits a local `terms_required` error and `CheckoutNotices` renders the message.

`CheckoutNotices` renders text-only checkout notices from local validation and Store API errors. E2E verifies the terms-blocked flow and that notice contents are safe text.
