Table of Contents
Most of you would know that WooCommerce does not allow customers to update the cart from the checkout page. Which means that you cannot change the quantity or delete the product from the checkout page. Customer needs to go back to cart page, update the cart, and then go to the checkout page again. This results in customers having to fill all the required information again. This is a bit frustrating for the customers, especially for guest users (which is a large majority).
In this post, we will discuss how to update the cart on the checkout page of WooCommerce. I have developed this feature in our Fun Friday event at the office. On Fun Fridays, we try to spend an entire day doing things which aren’t related to the core work activity of the person.
First, let’s take a look at the cart details table on the WooCommerce Checkout page:
Here, the customer cannot edit the quantity of the product or delete it. So we want to provide the functionality of changing the quantity and delete the product without having your customer leave the WooCommerce Checkout page.
In this post, we’ll talk about how to add quantity fields and how to update cart quantity on WooCommerce Block Checkout page as well as on the WooCommerce Classic Checkout pages. We’ll dive into the details of updating the cart directly on the WooCommerce checkout page and enhancing your store’s functionality like never before.
Let’s begin
If you want to skip this explanation, and instead want to implement the functionality on your store, then you can download the plugin named as Add Quantity Field in Woocommerce Checkout Pages which I have created. This plugin works smoothly on both classic and checkout blocks pages, making it easy to manage product quantities during checkout.
Download the Plugin From Github
- Clicking this plugin repository Add Quantity Field in Woocommerce Checkout Pages will take you to the github page where the plugin is hosted.
- Look for a green button labeled ‘Code’, clicking on the ‘Code’ button a dropdown will appear. Select ‘Download ZIP’ from the dropdown menu. This will download the plugin files as a ZIP archive.
- Go to your WordPress admin panel, navigate to Plugins > Add New > Upload Plugin.
- Click Choose File, select the ZIP file of the plugin you just downloaded, and click Install Now.
- Activate the plugin and start using the quantity field feature in checkout pages.
Add Quantity Fields on WooCommerce Classic Checkout Page
We need to modify the “Product” column in “Your order” table. We need to add the “Delete” icon and the “Quantity selector” for each item in the cart.
To achieve this, WooCommerce has given a filter which modifies the selected quantity displayed on the Your order table using the WooCommerce filter: woocommerce_checkout_cart_item_quantity.
Step 1: Adding Quantity Input and Delete icon
The code snippet adds a quantity input field and a delete icon to each item on the WooCommerce classic checkout page. This is achieved via using the filter ‘woocommerce_checkout_cart_item_quantity filter that allows customization of the quantity HTML output on the Your Order table of the checkout page. As a result, users will be able to either add the quantity of items or deleted an item using the added quantity filed and the delete icon.
We need to give the four parameters for the function “input_name”, “input_value”, “max_value”, “min_value”.
- input_name: It sets a unique name for the quantity input box based on the product ID.
- input_value: It will contain the selected quantity of the product.
- max_value: It will be the max stock number of the product.
- min_value: It will be the minimum value of the quantity selector.
Once all above steps are done, it will now display the delete button and quantity selector on the Your order table of the Checkout page.
// Filter to add quantity input and delete icon in classic checkout add_filter('woocommerce_checkout_cart_item_quantity', 'ts_checkout_item_quantity_input', 10, 3); function ts_checkout_item_quantity_input($product_quantity, $cart_item, $cart_item_key) { $product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key); $product_id = apply_filters('woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key); if (!$product->is_sold_individually()) { $product_quantity = '<div class="quantity-and-remove">'; $product_quantity .= woocommerce_quantity_input(array( 'input_name' => 'shipping_method_qty_' . $product_id, 'input_value' => $cart_item['quantity'], 'max_value' => $product->get_max_purchase_quantity(), 'min_value' => '0', ), $product, false); $product_quantity .= '<input type="hidden" name="product_key_' . $product_id . '" value="' . $cart_item_key . '">'; $product_quantity .= sprintf( '<a href="%s" class="delete" title="%s" data-product_id="%s" data-product_sku="%s"><span class="fas fa-trash-alt"></span></a>', esc_url(wc_get_cart_remove_url($cart_item_key)), __('Remove this item', 'woocommerce'), esc_attr($product_id), esc_attr($product->get_sku()) ); $product_quantity .= '</div>'; } return $product_quantity; }
This to the shop owners who are running or planning to run BOGO offers on their WooCommerce store…
BOGO deals are great for increasing your sales, but have you thought about which offers are bringing you more revenue and which offers are not performing that great?
Don’t just set a BOGO deal, track the revenue generated by your deals in real-time with the Flexi BOGO for WooCommerce plugin.
2. Updating the Cart & Changing Quantity
Adding this much won’t work, we need to make sure when a customer changes the quantity it will reflect on the cart total.
Changing Quantity
The following function updates the cart quantities based on user input and recalculates the cart totals. So when a customer changes the quantity, we need to take action and change the cart total.
add_action('woocommerce_checkout_update_order_review', 'ts_update_item_quantity_checkout'); function ts_update_item_quantity_checkout($post_data) { parse_str($post_data, $post_data_array); $updated_qty = false; foreach ($post_data_array as $key => $value) { if (substr($key, 0, 20) === 'shipping_method_qty_') { $id = substr($key, 20); WC()->cart->set_quantity($post_data_array['product_key_' . $id], $post_data_array[$key], false); $updated_qty = true; } } if ($updated_qty) WC()->cart->calculate_totals(); }
We need the CSS for the “Delete” button of the Your order table. So it should look like the WooCommerce cart delete button. So we need to add the CSS for it.
Once it is added we need to give the CSS to the delete button in the CSS file. The CSS has been shown below.
/* Styles for delete icon in classic checkout page */ .woocommerce table.shop_table .quantity-and-remove { display: flex; align-items: center; } .woocommerce table.shop_table .quantity-and-remove .delete { color: grey; /* Change icon color to grey */ font-size: 20px; font-weight: 700; height: 20px; line-height: 20px; text-align: center; text-decoration: none; vertical-align: middle; width: 20px; cursor: pointer; /* Hand cursor on hover */ margin-left: 5px; /* Adjust space between quantity input and delete icon */ } .woocommerce table.shop_table .quantity-and-remove .delete:hover { color: darkgrey; /* Change color on hover to a darker grey */ }
Output
When customers enter the classic checkout page they will have an input field to change the quantity. Also, a delete icon is present allowing users to remove items from the cart.
So, we are ready with the functionality where we can modify the quantity on the classic checkout page of WooCommerce.
After implementing the above, this is how the Your order table on the checkout page would look:
Add Quantity Fields on WooCommerce Checkout Blocks Page
For those online store owners who shifted to the newer WooCommerce Checkout Blocks, you can start customizing the checkout blocks page and make things a lot easier for your customers. By adding quantity fields to the checkout blocks page, shoppers can quickly adjust how many of each item they want before they finish their order. Plus, a handy delete button will let them remove items if they change their mind. This tweak will make your checkout process more user-friendly and efficient. Let’s see how this easy change can improve your store’s checkout experience!
If you want to skip the steps & download the plugin directly, please scroll at the bottom of this section after the “Output” section.
PHP Code: Enqueue Scripts and Handle Cart Updates
First, you need to add PHP code to enqueue necessary scripts and handle cart updates. This code registers and enqueues JavaScript and CSS files and sets up a callback to update cart quantities or remove items.
<?php /** * Plugin Name: Quantity Input Field in Checkout Page * Description: Adds a quantity selector to the checkout page and updates prices dynamically. * Version: 1.0 * Author: Tyche Softwares */ // Register and enqueue the JavaScript and CSS files function qsc_enqueue_scripts() { wp_enqueue_script( 'qsc-js', // Handle for the JavaScript file plugins_url('quantity-selector-checkout.js', __FILE__), // URL to the script array('jquery'), // Ensure jQuery is loaded first null, // Version of the script (optional) true // Load the script in the footer ); wp_localize_script( 'qsc-js', // Handle for the script 'qscParams', // Name of the JavaScript object to contain data array( 'ajax_url' => admin_url('admin-ajax.php'), // AJAX URL to be used in JavaScript ) ); // Enqueue the CSS file wp_enqueue_style( 'qsc-css', // Handle for the CSS file plugins_url('delete-icon.css', __FILE__) // URL to the CSS file ); } add_action('wp_enqueue_scripts', 'qsc_enqueue_scripts'); // Register the callback for cart updates add_action('woocommerce_blocks_loaded', function() { // Register the callback function woocommerce_store_api_register_update_callback( [ 'namespace' => 'quantity-selector', 'callback' => function( $data ) { // Check if itemId and quantity are set if (isset($data['itemId']) && isset($data['quantity'])) { $item_id = intval($data['itemId']); $quantity = intval($data['quantity']); // Update the cart item quantity foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { if ($cart_item['product_id'] === $item_id) { WC()->cart->set_quantity($cart_item_key, $quantity); } } // Recalculate cart totals WC()->cart->calculate_totals(); } elseif (isset($data['itemId']) && isset($data['action']) && $data['action'] === 'delete') { // Remove the item from the cart foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { if ($cart_item['product_id'] === intval($data['itemId'])) { WC()->cart->remove_cart_item($cart_item_key); } } // Recalculate cart totals WC()->cart->calculate_totals(); } }, ] ); }); // Filter to add quantity input and delete icon in classic checkout add_filter('woocommerce_checkout_cart_item_quantity', 'ts_checkout_item_quantity_input', 10, 3); function ts_checkout_item_quantity_input($product_quantity, $cart_item, $cart_item_key) { $product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key); $product_id = apply_filters('woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key); if (!$product->is_sold_individually()) { $product_quantity = '<div class="quantity-and-remove">'; $product_quantity .= woocommerce_quantity_input(array( 'input_name' => 'shipping_method_qty_' . $product_id, 'input_value' => $cart_item['quantity'], 'max_value' => $product->get_max_purchase_quantity(), 'min_value' => '0', ), $product, false); $product_quantity .= '<input type="hidden" name="product_key_' . $product_id . '" value="' . $cart_item_key . '">'; $product_quantity .= sprintf( '<a href="%s" class="delete" title="%s" data-product_id="%s" data-product_sku="%s"><span class="fas fa-trash-alt"></span></a>', esc_url(wc_get_cart_remove_url($cart_item_key)), __('Remove this item', 'woocommerce'), esc_attr($product_id), esc_attr($product->get_sku()) ); $product_quantity .= '</div>'; } return $product_quantity; } // Detect quantity change and recalculate totals add_action('woocommerce_checkout_update_order_review', 'ts_update_item_quantity_checkout'); function ts_update_item_quantity_checkout($post_data) { parse_str($post_data, $post_data_array); $updated_qty = false; foreach ($post_data_array as $key => $value) { if (substr($key, 0, 20) === 'shipping_method_qty_') { $id = substr($key, 20); WC()->cart->set_quantity($post_data_array['product_key_' . $id], $post_data_array[$key], false); $updated_qty = true; } } if ($updated_qty) WC()->cart->calculate_totals(); } ?>
JavaScript: Add Quantity Selector and Delete Button
Next, use JavaScript to modify the item name and add a quantity selector and delete icon to the checkout blocks. This script handles user interactions, sending updates to the server when quantities change or items are removed.
document.addEventListener('DOMContentLoaded', function() { const { registerCheckoutFilters, extensionCartUpdate } = window.wc.blocksCheckout; // Function to modify the item name and include a quantity selector and delete icon const modifyItemName = (defaultValue, extensions, args) => { const isSummaryContext = args?.context === 'summary'; if (!isSummaryContext) { return defaultValue; } // Retrieve the current quantity of the cart item const quantity = args?.cartItem?.quantity || 1; // Create the HTML for the quantity selector and delete icon const quantitySelector = ` <div class="quantity-selector"> <label for="quantity-${args.cartItem.id}">Quantity:</label> <input type="number" id="quantity-${args.cartItem.id}" name="quantity-${args.cartItem.id}" value="${quantity}" min="1" max="${args.cartItem.quantity_limits?.maximum || 10}" data-item-id="${args.cartItem.id}" class="quantity-input" /> <span class="delete-icon" data-item-id="${args.cartItem.id}" title="Remove Item"><span class="fas fa-trash-alt"></span></span> </div> `; // Return the modified item name with the quantity selector and delete icon return `${defaultValue}${quantitySelector}`; }; // Register the filter registerCheckoutFilters('quantity-selector', { itemName: modifyItemName, }); // Debounce function to limit the rate of function execution function debounce(func, delay) { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), delay); }; } // Lock to prevent simultaneous updates and store pending updates let isUpdating = false; let pendingUpdate = null; // Handle quantity change and send data to the server with debouncing const handleQuantityChange = debounce(function(event) { if (event.target.classList.contains('quantity-input')) { const itemId = event.target.getAttribute('data-item-id'); const quantity = event.target.value; if (isUpdating) { pendingUpdate = { itemId, quantity }; return; // Queue the update } isUpdating = true; extensionCartUpdate({ namespace: 'quantity-selector', data: { itemId: itemId, quantity: quantity }, }).then(response => { // Process the next pending update if any if (pendingUpdate) { const nextUpdate = pendingUpdate; pendingUpdate = null; handleQuantityChange({ target: { classList: { contains: () => true }, getAttribute: () => nextUpdate.itemId, value: nextUpdate.quantity } }); } }).finally(() => { isUpdating = false; // Release the lock after update }); } }, 1000); // Debounce delay of 1000ms // Handle quantity change event document.addEventListener('change', handleQuantityChange); // Handle delete icon click and send data to the server document.addEventListener('click', function(event) { if (event.target.closest('.delete-icon')) { // Ensure closest .delete-icon is targeted const itemId = event.target.closest('.delete-icon').getAttribute('data-item-id'); // Use closest to get parent delete-icon's data-item-id extensionCartUpdate({ namespace: 'quantity-selector', data: { itemId: itemId, action: 'delete' }, }); } }); });
CSS: Style the Quantity Selector and Delete Icon
Finally, add some CSS to style the quantity selector and delete icon, making the delete button to be visually appealing.
/* Styles for delete icon */ .quantity-selector .delete-icon { color: grey; /* Change icon color to grey */ display: inline-block; font-size: 20px; font-weight: 700; height: 20px; line-height: 20px; text-align: center; text-decoration: none; vertical-align: middle; width: 20px; cursor: pointer; /* Changes cursor to hand symbol on hover */ } .quantity-selector .delete-icon:hover { color: darkgrey; /* Optional: Change color on hover to a darker grey */ }
Output
Imagine a customer shopping at your online store adds two items to their cart. When they proceed to the checkout page, they have the flexibility to adjust the quantities of their products or delete the items from the checkout blocks page as well.
Following the above steps, would have helped you to add the quantity selector and the delete icon for the each item of the Your order table of the classic checkout and the checkout blocks page.
If you find it challenging to add these code snippets manually into your code editor, don’t worry! You can easily implement this functionality by downloading and installing our pre-built plugin.
If you have any feedback, then you can let me know in the comments below.
I can’t get it to work 🙁 I turn on the plugin but nothing!
Hi Ronnie,
The plugin provided in the post works well in the updated WooComemrce version (9.0.0) specifically on the classic checkout page. Please try switching to a default WordPress theme and deactivating other plugins except WooCommerce to check if there is a theme/plugin conflict. Ensure that the version of WooCommerce is up to date. If the issue persists, please get back to us with the additional customization details you have implemented on your site, so that we can assist you better.
right now this is not working with Hello Theme and elementor. can you do something
how to woocommerce update item sub total in checkout page. and can how i override that is
Please any video tutorial on this?
Sometimes I get error.
CRITICAL Uncaught Error: Call to a member function get_tax_class() on null in /home/xxxx/public_html/wp-content/plugins/woocommerce/includes/class-wc-cart-totals.php:225
not everytime. but still annoying.. and hard to replicate