Home
Wiki
Home
Wiki
  1. 3. Reusables
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 1. Structure
      • Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • Overview
      • Addresses
      • BillingRetail
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • Company
      • General
      • Login
      • LoginModal
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ShoppingListsButton
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Register
      • Shipping
      • ShoppingLists
      • ShoppingListsNavbar
      • Toast
      • Users
      • VariantContent
      • WishlistButton
      • Services
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • Overview
        • theme.js
      • Css / Scss
        • Overview
        • ThemeClasses
    • 5. SDK
      • Overview
      • LiquidGlobals
      • ServicesSDK
  1. 3. Reusables

AddressForm

Purpose#

AddressForm is the reusable that drives the address selection + address form UX in Checkout.
It renders saved addresses (when present), allows editing, supports creating a new address, optionally collects invoice data (billing), and synchronizes billing/shipping via a shared Alpine store.
On progression it also updates the Checkout state by calling servicesreusabledefault.updateCheckout(...).

Where it's rendered#

It’s not rendered directly from a component; it’s rendered by BillingRetail (Checkout billing section).
From Reusables/BillingRetail/Default.liquid:
{% render 'Reusables\\AddressForm\\Default',
  addressType: 'billing',
  addresses: addresses,
  countriesList: countriesList,
  headQuarterAddress: headQuarterAddress
%}

{% render 'Reusables\\AddressForm\\Default',
  addressType: 'shipping',
  addresses: addresses,
  countriesList: countriesList,
  headQuarterAddress: headQuarterAddress
%}

Inputs (Liquid render parameters)#

Source: Reusables/AddressForm/Default.liquid.
The reusable is initialized via Alpine using:
x-data='addressformreusabledefault.initComponent(
  {{ addresses | serialize | escape }},
  {{ countriesList }},
  {{ deliveryZonesEnabled }},
  "{{ addressType }}",
  "{{ inValidAddressMessage }}",
  {{ modalTranslationsInvoice }},
  "{{ addressErrorMessage }}",
  "{{ addressUpdateErrorMessage }}",
  "{{ postalCodesErrorMessage }}",
  {{ isB2bCustomer }}
)'

Model shape (storefront example)#

Below is a sanitized excerpt from a real Checkout model dump (the fields used by this reusable via addresses and countriesList).
{
  "countriesList": [
    {
      "code": "GR",
      "name": "Greece"
    },
    ...
  ],
  "addresses": [
    {
      "name": "",
      "isSelectable": true,
      "address": {
        "id": "Address Id",
        "firstName": "Sample first name",
        "lastName": "Sample last name",
        "phoneNumber": "Sample phone",
        "address1": "Sample address",
        "city": "Sample city",
        "state": "Sample state",
        "country": "Sample country",
        "countryCode": "GR",
        "postalCode": "10552",
        "email": "sample@example.com"
      },
      "requiresInvoice": false
    }
  ]
}

Required fields#

addresses#

Expected input is an array; each entry is expected to look like:
name (string)
Used as a “branch label” in some display cases.
isSelectable (boolean)
Used when deliveryZonesEnabled is true.
address (object)
The actual address fields that the forms bind to (examples seen in Liquid/JS):
id
firstName, lastName
phoneNumber
email
address1
postalCode
city
state
country, countryCode
label (optional; shown in some recaps)
additionalInfo (used for new addresses)

countriesList#

Array of items:
code
name

addressType#

String, passed as 'billing' or 'shipping'.

Optional fields#

headQuarterAddress (object)
Used only in the B2B flow.
In Default.liquid it’s displayed when isB2bCustomer == true and addressType == 'billing'.
deliveryZonesEnabled (boolean)
Derived from GlobalData.Settings.deliveryZonesEnabled.
When enabled, the country/postal code behavior changes and extra validity checks apply.
Translation/error strings
inValidAddressMessage, addressErrorMessage, addressUpdateErrorMessage, postalCodesErrorMessage.

Template behavior (Liquid + Alpine)#

Source: Reusables/AddressForm/Default.liquid.
Key behaviors:
Saved address list rendered with x-for over displayAddresses (computed method in JS).
UI has two modes:
Retail: editable forms + saved address selection.
B2B:
For billing, it shows headQuarterAddress recap (read-only).
For shipping, it still renders radios and uses the shared store for selection.
The form fields’ ids follow patterns that Default.js depends on:
Edit form fields: ${addressType}-edit-${index}-<field>
New form fields: ${addressType}-new-${index}-<field>
Invoice fields: company-${addressType}-edit-${index}-<field>

Data contract (JS runtime)#

addressformreusabledefault.initComponent(...)#

From Reusables/AddressForm/Default.js:
initComponent(
  addresses,
  countriesList,
  deliveryZonesEnabled,
  addressType,
  inValidAddressMessage,
  modalTranslationsInvoice,
  addressErrorMessage,
  addressUpdateErrorMessage,
  postalCodesErrorMessage,
  isB2bCustomer
)
Notes:
addresses can be an array, an object, or null; it gets normalized:
Internally it stores:
addresses: normalizedAddresses.map(a => a.address)
branchesNames: normalizedAddresses.map(a => a.name || '')
storedAddressesValidity:
deliveryZonesEnabled ? normalizedAddresses.map(a => a.isSelectable) : normalizedAddresses.map(() => true)

JavaScript#

Source: Reusables/AddressForm/Default.js.

init()#

Sets up the initial address arrays and the billing/shipping synchronization.
Retail flow (!isB2bCustomer):
Creates blank “new address” rows via startNewAddress().
In billing mode, it also seeds $store.sharedAddresses.addresses and $store.sharedAddresses.invoices.
In shipping mode, it reads back from $store.sharedAddresses.
Watches $store.sharedAddresses.updateShippingAddresses to keep the two forms in sync.
B2B flow (isB2bCustomer):
Billing mode:
Reads field values from the DOM and pushes them into $store.sharedAddresses.
Then keeps only the first address and calls saveTemporarilyAddress(0).
Shipping mode:
Uses $store.sharedAddresses.addresses.

displayAddresses() / displayInvoices()#

These methods decide what list items to show.
They hide “blank” placeholder entries depending on:
showNewAddressWrap
newAddressOn
addressType (billing vs shipping)
whether there were saved addresses initially (normalizedAddresses.length > 0)

startEditing(index) / cancelEditing(index)#

startEditing:
Enables edit mode for a selected address.
Takes snapshots in originalData[index] and originalInvoiceData[index].
Clears errors and, when deliveryZonesEnabled, normalizes country values and triggers onCountryChange(...).
cancelEditing:
Restores snapshots.
Resets touched/validity state.

saveTemporarilyAddress(index, type = 'edit')#

Validates the address form fields and stores the normalized data.
Key decisions:
Determines whether it’s an edit vs new form based on:
addresses[index]?.editFlag
addresses[index]?.tempType === 'new'
For delivery zones:
Updates $store.sharedAddresses.validAddresses[index].
Shows a blocking toast (inValidAddressMessage) and resets the current checkout step if the address is not selectable.
Writes updates into $store.sharedAddresses (retail flow).
If the address is new and addressType === 'billing', it continues into saveTemporarilyInvoice(...).

saveTemporarilyInvoice(index, type = 'edit')#

Validates invoice fields (billing only), updates $store.sharedAddresses.invoices, and may persist the address/invoice in the profile via updateAddressDataProfile(...).
Also flips $store.sharedAddresses.updateShippingAddresses = true to sync shipping.

nextCheckoutStep()#

Builds an updated checkout payload from $store.checkout.data + $store.sharedAddresses and calls:
servicesreusabledefault.updateCheckout(updatedCheckoutData, stepName)
Behavior differs per addressType:
Billing:
Sets documentType to Invoice vs Receipt based on invoiceOption.
If shipping is already valid, it updates the shipping step too.
Shipping:
Always updates checkout with billingShippingAddress as the step.

updateAddressDataProfile(addressId, type = 'edit')#

Persists an address to the user profile (create or update) using:
servicesreusabledefault.createUserAddress(dataToSend)
servicesreusabledefault.updateUserAddress(dataToSend, addressId)

validateField(field)#

Client validation rules for required fields, email format, and select validation.
For SELECT required fields, behavior depends on delivery zones:
When deliveryZonesEnabled is true, it also consults $store.sharedAddresses.validAddresses[this.selectedAddressIndex].

onCountryChange(index, showToast = false)#

Delivery-zone-specific behavior:
Syncs countryCode with country (using countriesList).
Fetches postal codes:
Updates postalCodes array and validates/sets postalCode field accordingly.

Invoice helpers#

validateInvoice() toggles invoice mode and may open a modal confirmation via $store.modal.
startInvoiceEditing(index) and isInvoiceModified(index) manage invoice edit state.

Global Alpine stores#

Directly used:
$store.sharedAddresses
addresses, invoices
updateAddress(index, data, ...)
updateInvoice(index, data)
updateValidAddress(index, boolean)
validAddresses[...]
updateShippingAddresses
$store.checkout
data (read + write)
steps[...] validity
validateStep(stepName, ...)
setCurrent(stepName)
isUpdating, isReady
$store.toast
add(...), remove(...), removeAll()
$store.modal
open(...), close()

Services / API calls#

From Reusables/AddressForm/Default.js:
servicesreusabledefault.updateCheckout(updatedCheckoutData, stepName)
servicesreusabledefault.createUserAddress(dataToSend)
servicesreusabledefault.updateUserAddress(dataToSend, addressId)
servicesreusabledefault.fetchPostalCodes(countryCode)

Dependencies#

Reusables/AddressForm/Default.liquid
Reusables/AddressForm/Default.js
Reusables/AddressForm/Default.json (translations)
Reusables/BillingRetail/Default.liquid (render site)
$store.checkout, $store.sharedAddresses, $store.toast, $store.modal in Assets/js/theme.js
servicesreusabledefault (SDK)

Notes#

The logic depends heavily on DOM id naming conventions (${addressType}-edit-${index}-... etc). If you change ids in Liquid, you must update the JS selectors.
There are two different “persistence” paths:
Checkout update (updateCheckout) – used to progress checkout steps.
Profile persistence (createUserAddress / updateUserAddress) – used when storing/updating addresses.
When deliveryZonesEnabled is enabled, postal code list is fetched per country; the postal code field becomes a select-driven validation path.

Examples#

Billing in checkout:
{% render 'Reusables\\AddressForm\\Default',
  addressType: 'billing',
  addresses: model.addresses,
  countriesList: model.countriesList,
  headQuarterAddress: GlobalData.Settings.IsB2bCustomer ? model.checkout.billingAddress : nil
%}
Shipping in checkout:
{% render 'Reusables\\AddressForm\\Default',
  addressType: 'shipping',
  addresses: model.addresses,
  countriesList: model.countriesList,
  headQuarterAddress: GlobalData.Settings.IsB2bCustomer ? model.checkout.billingAddress : nil
%}
Modified at 2026-04-14 13:18:56
Previous
BillingRetail
Next
AnnouncementModal
Built with