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> { active?: boolean; disabled?: boolean; handleValidation?: () => boolean; handlePlaceOrder: (ctx: HandlePlaceOrderContext) => Promise<void>; slots?: { Content?: SlotProps<ContentSlotContext>; };}-
Set the
activeproperty to true to have the container in reactive mode (it is visible and responds to system events). If it is set to false, the container is deactivated (it does not subscribe to system events and is not rendered). -
The
disabledproperty set to true forces the Place Order button to be disabled. -
The
handleValidationproperty is a handler used to perform some validation checks before submitting the checkout forms and placing the order. -
The
handlePlaceOrderproperty 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 thehandleValidationreturns 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
HandlePlaceOrderContextinterface:export interface HandlePlaceOrderContext {code: string;cartId: string;} -
The
slotsproperty is an object containing the following properties:- The
Contentproperty 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;} - The
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, billing, and terms & conditions 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';
import { scrollToElement } from '../../scripts/checkout.js';
const LOGIN_FORM_NAME = 'login-form';const SHIPPING_FORM_NAME = 'selectedShippingAddress';const BILLING_FORM_NAME = 'selectedBillingAddress';const TERMS_AND_CONDITIONS_FORM_NAME = 'checkout-terms-and-conditions__form';
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); }
const termsAndConditionsForm = forms[TERMS_AND_CONDITIONS_FORM_NAME];
if (success && termsAndConditionsForm) { success = termsAndConditionsForm.checkValidity(); if (!success) scrollToElement($termsAndConditions); }
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),