Black Friday & Cyber Monday SUPER SALE ALL WEEK:
Grab 40% OFF on plugins
Days
Hours
Minutes
Seconds

How to Add Quantity Fields on WooCommerce (Both Classic & Checkout Blocks) Pages?

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;
}

flexi bogo cta banner image


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:

How to Add Quantity Fields on WooCommerce (Both Classic & Checkout Blocks) Pages? - Tyche Softwares


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.

How to Add Quantity Fields on WooCommerce (Both Classic & Checkout Blocks) Pages? - Tyche Softwares

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.

 

Browse more in: WooCommerce, Code Snippets, WooCommerce How Tos, WooCommerce Tutorials

Share It:

Subscribe
Notify of
16 Comments
Newest
Oldest
Inline Feedbacks
View all comments
4 months ago

I can’t get it to work 🙁 I turn on the plugin but nothing!

Editor
4 months ago
Reply to  Ronnie

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.

MEHEDI
1 year ago

right now this is not working with Hello Theme and elementor. can you do something

Gapu
2 years ago

how to woocommerce update item sub total in checkout page. and can how i override that is

Last edited 2 years ago by Gapu
Peter
2 years ago

Please any video tutorial on this?

rio
2 years ago

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

16
0
Would love your thoughts, please comment.x
()
x