Add a quantity field to Ajax add to cart button on WooCommerce shop page

17,101

Solution 1

Updated on 2021

For WooCommerce versions from 3.2 to 5+, Optimized jQuery code and Removed a quantity bug. Added quantity reset after add to cart.


The following custom function is hooked in woocommerce_loop_add_to_cart_link filter hook and adds a quantity input field to each product on WooCommerce archives pages and other product loops. We use here mostly the original WooCommerce code.

A bit of jQuery code is necessary to update the data-quantity attribute on the add to cart button when customer changes the quantity. Some styling might be needed, depending on your client wishes (and on your theme).

An additional section to hide the "View cart" button is located at the end.

The code:

add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_loop_ajax_add_to_cart', 10, 2 );
function quantity_inputs_for_loop_ajax_add_to_cart( $html, $product ) {
    if ( $product && $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() && ! $product->is_sold_individually() ) {
        // Get the necessary classes
        $class = implode( ' ', array_filter( array(
            'button',
            'product_type_' . $product->get_type(),
            $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
            $product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
        ) ) );

        // Embedding the quantity field to Ajax add to cart button
        $html = sprintf( '%s<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>',
            woocommerce_quantity_input( array(), $product, false ),
            esc_url( $product->add_to_cart_url() ),
            esc_attr( isset( $quantity ) ? $quantity : 1 ),
            esc_attr( $product->get_id() ),
            esc_attr( $product->get_sku() ),
            esc_attr( isset( $class ) ? $class : 'button' ),
            esc_html( $product->add_to_cart_text() )
        );
    }
    return $html;
}

add_action( 'wp_footer' , 'archives_quantity_fields_script' );
function archives_quantity_fields_script(){
    ?>
    <script type='text/javascript'>
        jQuery(function($){
            // Update data-quantity
            $(document.body).on('click input', 'input.qty', function() {
                $(this).parent().parent().find('a.ajax_add_to_cart').attr('data-quantity', $(this).val());
                $(".added_to_cart").remove(); // Optional: Removing other previous "view cart" buttons
            }).on('click', '.add_to_cart_button', function(){
                var button = $(this);
                setTimeout(function(){
                    button.parent().find('.quantity > input.qty').val(1); // reset quantity to 1
                }, 1000); // After 1 second

            });
        });
    </script>
    <?php
}

Code goes in functions.php file of your active child theme (active theme).
Tested and works on WooCommerce version 4.1.1 and WordPress 4.5.1 on Storefront theme.


Hiding "View cart" button (when using Ajax add to cart):

1). You can add this CSS rule to the styles.css file located in your active theme:

a.added_to_cart.wc-forward {
    display:none;
}

2). You can use the following hoocked function (first option is the best way):

add_action( 'wp_head' , 'hide_ajax_view_cart_button' );
function hide_ajax_view_cart_button(){
    if( is_shop() || is_product_category() || is_product_tag() ): ?>
    <style>
        a.added_to_cart.wc-forward {
            display:none;
        }
    </style>
    <?php endif;
}

Code goes in function.php file of your active child theme (active theme).

Solution 2

Does everything as above, without the "quantity bug".

The code:

add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_loop_ajax_add_to_cart', 10, 2 );
function quantity_inputs_for_loop_ajax_add_to_cart( $html, $product ) {
    if ( $product && $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() && ! $product->is_sold_individually() ) {
        // Get the necessary classes
        $class = implode( ' ', array_filter( array(
            'button',
            'product_type_' . $product->get_type(),
            $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
            $product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
        ) ) );

        // Adding embeding <form> tag and the quantity field
        $html = sprintf( '%s%s<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>%s',
        '<form class="cart">',
        woocommerce_quantity_input( array(), $product, false ),
        esc_url( $product->add_to_cart_url() ),
        esc_attr( isset( $quantity ) ? $quantity : 1 ),
        esc_attr( $product->get_id() ),
        esc_attr( $product->get_sku() ),
        esc_attr( isset( $class ) ? $class : 'button' ),
        esc_html( $product->add_to_cart_text() ),
        '</form>'
        );
    }
    return $html;
}

add_action( 'wp_footer' , 'archives_quantity_fields_script' );
function archives_quantity_fields_script(){
    //if( is_shop() || is_product_category() || is_product_tag() ): ?>
    <script type='text/javascript'>
        jQuery(function($){
            // Update quantity on 'a.button' in 'data-quantity' attribute (for ajax)
            $(".add_to_cart_button.product_type_simple").on('click', function() { var $button = $(this); $button.data('quantity', $button.parent().find('input.qty').val()); });        
            // remove old "view cart" text, only need latest one thanks!
            $(document.body).on("adding_to_cart", function() {
                $("a.added_to_cart").remove();
            });
        });
    </script>
    <?php //endif;
}

References:

@LoicTheAztec's entry above 11 Feb 2018.

@braciawrite's and @andrewmclagan's GitHub entries on 11 Dec 2015 and 15 Mar 2018 respectively.

https://gist.github.com/webaware/6260326

Note:

Code should perform the check when "add_to_cart" button is pressed, not on quantity change.

I've commented out the if and endif statements under function "archives_quantity_fields_script" as I am running this code on a custom page with WooCommerce products.

Hope this helps!

Share:
17,101
Nevin Thomas
Author by

Nevin Thomas

Updated on June 13, 2022

Comments

  • Nevin Thomas
    Nevin Thomas almost 2 years

    I am new to Woocommerce. I was trying to show the quantity box in the shop page. I have used the below code and it's working as expected:

    add_action( 'woocommerce_before_shop_loop', 'handsome_bearded_guy_select_variations' );
    
    function handsome_bearded_guy_select_variations() {
    remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_single_add_to_cart', 30 );
    }
    

    But the problem is that ajax add to cart button got replaced with default one.

    How can I enable back the ajax functionality on add to cart button with quantity field for Woocommerce archives pages?

  • cweitat
    cweitat almost 5 years
    this code works as of 27th Jul 2019. Accepted answer has syntax error
  • danielmeade
    danielmeade almost 4 years
    As of WooCommerce 4.0 this solution seems to no longer work.
  • Victor Sokoliuk
    Victor Sokoliuk over 3 years
    Maybe is there, but I can not find, so can you advise the code to add and remove products by clicking on quantity +/- or maybe I can try to modify the current code for this purpose?
  • aas
    aas over 3 years
    Anyone here to help me am in October 2020 and still quantity is not updating
  • aas
    aas over 3 years
    WordPress 5.5.1