Skip to content

Validate address in My Account

Use the AddressValidation container to present both the original and suggested addresses from your verification service, letting shoppers choose before saving. This tutorial shows how to integrate the container in the commerce-addresses block.

Validate address

AddressValidation displayed in a modal

Overview

At a high level:

  • Call your address verification service on form submit.
  • If it returns a suggestion, open a modal and render AddressValidation.
  • If the shopper selects the suggestion, populate the form with the suggested data and re-submit; otherwise, retain the original form values.

Integration in commerce-addresses block

Update your blocks/commerce-addresses/commerce-addresses.js to:

  • Import AddressValidation
  • Pass forwardFormRef, onAddressData, and onSubmit to Addresses
  • When a suggestion exists, show a modal with AddressValidation and two actions: Edit Address and Save Address
// blocks/commerce-addresses/commerce-addresses.js
import { Addresses } from '@dropins/storefront-account/containers/Addresses.js';
import AddressValidation from '@dropins/storefront-account/containers/AddressValidation.js';
import { render as accountRenderer } from '@dropins/storefront-account/render.js';
import { Button, provider as UI } from '@dropins/tools/components.js';
import { readBlockConfig } from '../../scripts/aem.js';
import {
CUSTOMER_ADDRESS_PATH,
CUSTOMER_LOGIN_PATH,
checkIsAuthenticated,
rootLink,
} from '../../scripts/commerce.js';
import { showModal, removeModal } from './modal-utils.js';
const validateAddress = async (address) => {
// Call your service with the form data
// const result = await fetch(...)
// return result.suggestedAddress || null
// Example mocked suggestion
return {
city: 'Bainbridge Island',
countryCode: 'US',
postcode: '98110-2450',
region: { regionCode: 'WA', regionId: 1 },
street: ['123 Winslow Way E'],
telephone: '555-123-4567',
};
};
const finalizeSubmission = (setContainerProps, formRef, updates = {}) => {
setContainerProps({ onSubmit: null, ...updates });
setTimeout(() => formRef.current?.requestSubmit(), 1);
};
const renderAddressValidation = async ({
originalAddress,
suggestedAddress,
onEdit,
onSave,
}) => {
const container = document.createElement('div');
const addressValidation = document.createElement('div');
const actionsContainer = document.createElement('div');
const editAddressButton = document.createElement('div');
const saveAddressButton = document.createElement('div');
actionsContainer.appendChild(editAddressButton);
actionsContainer.appendChild(saveAddressButton);
container.appendChild(addressValidation);
container.appendChild(actionsContainer);
actionsContainer.classList.add('actions-container');
await showModal(container);
let selectedAddress, currentSelection;
provider.render(AddressValidation, {
selectedAddress: 'suggested',
originalAddress,
suggestedAddress,
handleSelectedAddress: async ({ address, selection }) => {
selectedAddress = address;
currentSelection = selection;
},
})(addressValidation);
UI.render(Button, {
children: 'Edit Address',
size: 'medium',
variant: 'secondary',
onClick: () => {
if (currentSelection === 'suggested') {
onEdit(selectedAddress);
}
removeModal();
},
})(editAddressButton);
UI.render(Button, {
children: 'Save Address',
size: 'medium',
variant: 'primary',
onClick: () => {
const updates = {};
if (currentSelection === 'suggested') {
updates.inputsDefaultValueSet = selectedAddress;
}
removeModal();
onSave(updates);
},
})(saveAddressButton);
};
export default async function decorate(block) {
const { 'minified-view': minifiedViewConfig = 'false' } = readBlockConfig(block);
if (!checkIsAuthenticated()) {
window.location.href = rootLink(CUSTOMER_LOGIN_PATH);
return;
}
let originalAddress;
const formRef = { current: null };
const addressesContainer = await accountRenderer.render(Addresses, {
minifiedView: minifiedViewConfig === 'true',
withActionsInMinifiedView: false,
withActionsInFullSizeView: true,
routeAddressesPage: () => rootLink(CUSTOMER_ADDRESS_PATH),
forwardFormRef: formRef,
onAddressData: (values) => {
originalAddress = values?.data;
},
onSubmit: async (event, formValid) => {
if (!formValid) return;
const setContainerProps = (updates) => {
addressesContainer.setProps((prev) => ({ ...prev, ...updates }));
};
const suggestedAddress = await validateAddress(originalAddress);
if (!suggestedAddress) {
finalizeSubmission(setContainerProps, formRef);
return;
}
await renderAddressValidation({
originalAddress,
suggestedAddress,
onEdit: (selectedAddress) => {
setContainerProps({ inputsDefaultValueSet: selectedAddress });
},
onSave: (updates) => {
finalizeSubmission(setContainerProps, formRef, updates);
},
});
},
})(block);
}
// modal-utils.js
import createModal from '../modal/modal.js';
let modal;
export const showModal = async (content) => {
modal = await createModal([content]);
modal.showModal();
};
export const removeModal = () => {
if (!modal) return;
modal.removeModal();
modal = null;
};

Optional styles

/* Minimal layout for the modal */
.modal-content {
padding: 32px;
}
.actions-container {
display: flex;
gap: 16px;
margin-top: 48px;
justify-content: flex-end;
}

Next steps

  • See the AddressValidation container container for props and behaviors.
  • Ensure your suggestion matches the CustomerAddressInput shape expected by the Addresses container.