PlaceOrder container
The PlaceOrder
container is designed to handle the final step in the checkout process, where the user confirms and places their order. You can configure it to disable the button, perform some validations before submitting the form, handle the place order action, and manage the content slot for the place order button.
PlaceOrder configurations
The PlaceOrder
container provides the following configuration options:
These configuration options are implementing the PlaceOrderProps
interface:
PlaceOrderProps interface
The PlaceOrder
container receives an object as parameter which implements the PlaceOrderProps
interface with the following properties:
export interface PlaceOrderProps extends HTMLAttributes<HTMLDivElement> { disabled?: boolean; handleValidation?: () => boolean; handlePlaceOrder: (ctx: HandlePlaceOrderContext) => Promise<void>; slots?: { Content?: SlotProps<ContentSlotContext>; };}
disabled
property set to true forces the Place Order button to be disabled.handleValidation
property is a handler used to perform some validation checks before submitting the checkout forms and placing the order.handlePlaceOrder
property is a handler used to perform some actions related to the order placement process. It is executed when the Place Order button is clicked and if the handleValidation
returns true (in case it is provided, otherwise it will be executed without validation checks).The asynchronous function provided accepts a context as parameter which implements the HandlePlaceOrderContext
interface:
export interface HandlePlaceOrderContext { code: string; cartId: string;}
slots
property is an object containing the following properties:Content property
The Content
property is a handler used to render the PlaceOrder container content based on the selected payment method code:
export type SlotProps<T = any> = ( ctx: T & DefaultSlotContext<T>, element: HTMLDivElement | null) => Promise<void> | void;
export interface ContentSlotContext { code: string;}
Example 1: Render performing validations and a handler for order placement
The following example renders the PlaceOrder
container on a checkout page using the PaymentServices
drop-in component as a payment method. It includes functionality to validate login, shipping, and billing forms before placing an order. If the validation passes, it attempts to place the order and handles any errors.
// Checkout Dropinimport PlaceOrder from '@dropins/storefront-checkout/containers/PlaceOrder.js';import { render as CheckoutProvider } from '@dropins/storefront-checkout/render.js';
// Order Dropin Modulesimport * as orderApi from '@dropins/storefront-order/api.js';
// Payment Services Dropinimport { PaymentMethodCode } from '@dropins/storefront-payment-services/api.js';
const LOGIN_FORM_NAME = 'login-form';const SHIPPING_FORM_NAME = 'selectedShippingAddress';const BILLING_FORM_NAME = 'selectedBillingAddress';
const $placeOrder = checkoutFragment.querySelector('.checkout__place-order');
const shippingFormRef = { current: null };const billingFormRef = { current: null };const creditCardFormRef = { current: null };
CheckoutProvider.render(PlaceOrder, { handleValidation: () => { let success = true; const { forms } = document;
const loginForm = forms[LOGIN_FORM_NAME];
if (loginForm) { success = loginForm.checkValidity(); if (!success) scrollToElement($login); }
const shippingForm = forms[SHIPPING_FORM_NAME];
if ( success && shippingFormRef.current && shippingForm && shippingForm.checkVisibility() ) { success = shippingFormRef.current.handleValidationSubmit(false); }
const billingForm = forms[BILLING_FORM_NAME];
if ( success && billingFormRef.current && billingForm && billingForm.checkVisibility() ) { success = billingFormRef.current.handleValidationSubmit(false); }
return success; }, handlePlaceOrder: async ({ cartId, code }) => { await displayOverlaySpinner(); try { // Payment Services credit card if (code === PaymentMethodCode.CREDIT_CARD) { if (!creditCardFormRef.current) { console.error('Credit card form not rendered.'); return; } if (!creditCardFormRef.current.validate()) { // Credit card form invalid; abort order placement return; } // Submit Payment Services credit card form await creditCardFormRef.current.submit(); } // Place order await orderApi.placeOrder(cartId); } catch (error) { console.error(error); throw error; } finally { removeOverlaySpinner(); } },})($placeOrder),
Example 2: Render providing explicit content for the button
The following example renders the PlaceOrder
container on a checkout page providing different text for the Place Order button depending on the selected payment method.
// Checkout Dropinimport PlaceOrder from '@dropins/storefront-checkout/containers/PlaceOrder.js';import { render as CheckoutProvider } from '@dropins/storefront-checkout/render.js';
// Order Dropin Modulesimport * as orderApi from '@dropins/storefront-order/api.js';
const $placeOrder = checkoutFragment.querySelector('.checkout__place-order');
CheckoutProvider.render(PlaceOrder, { handlePlaceOrder: async ({ cartId }) => { orderApi.placeOrder(cartId).catch(console.error); }, slots: { Content: (ctx) => { const content = document.createElement('span'); ctx.appendChild(content);
function setContent(currentCtx) { switch (currentCtx.code) { case 'checkmo': { content.textContent = 'Pay Now'; break; } case 'banktransfer': { content.textContent = 'Make a transfer'; break; } default: { content.textContent = currentCtx.dictionary.Checkout.PlaceOrder.button; } } }
setContent(ctx); ctx.onChange(setContent); }, },})($placeOrder),