Skip to content

Validate a saved address

When your address verification service returns a suggested address that differs from what a shopper entered, you can let them choose between the two before saving. This how-to shows you how to add that confirmation step using the AddressValidation container.

Validate address

AddressValidation displayed in a modal
  • Edit the addresses block — blocks/commerce-addresses/commerce-addresses.js
  • Edit the AddressValidation container
  • Edit the Addresses container
  • Create the modal helper — blocks/commerce-addresses/modal-utils.js

By the end of this how-to, you’ll have:

  • A modal in your commerce-addresses block that renders the AddressValidation container when your verification service returns a suggested address.
  • An onSubmit handler on the Addresses container that calls your verification service before saving, using forwardFormRef and onAddressData to read the submitted form values.
  • A modal-utils.js helper that opens and closes the validation modal.

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;
};
/* Minimal layout for the modal */
.modal-content {
padding: 32px;
}
.actions-container {
display: flex;
gap: 16px;
margin-top: 48px;
justify-content: flex-end;
}
  • See the AddressValidation container container for props and behaviors.
  • Ensure your suggestion matches the CustomerAddressInput shape expected by the Addresses container.
  • See Validate a shipping address to add the same confirmation step before a shopper places an order at checkout.