10

I’m building custom WordPress and WooCommerce theme and adding custom plus and minus buttons to Product page quantity field. The buttons do update quantity input's value and I also receive "Item has been added to your cart" notification (on Product page) when I submit Add to Cart. But the cart page doesn’t show any items, neither says the cart is empty.

I can not work out which WooCommerce JS function I’m suppose to hook into, neither how to hook into it. Could I ask for help please?! Thanks in advance!

My HTML layout:

<div class="quantity">
    <label class="quantity__label" for="<?php echo esc_attr( $input_id ); ?>"><?php esc_html_e( 'Quantity:', 'woocommerce' ); ?></label>
    <div class="quantity__wrapper">
        <input type="button" value="-" class="quantity__button quantity__remove js-qty-remove" />
        <input
            type="text"
            id="<?php echo esc_attr( $input_id ); ?>"
            class="input-text qty text quantity__input"
            step="<?php echo esc_attr( $step ); ?>"
            min="<?php echo esc_attr( $min_value ); ?>"
            max="<?php echo esc_attr( 0 < $max_value ? $max_value : '' ); ?>"
            name="<?php echo esc_attr( $input_name ); ?>"
            value="<?php echo esc_attr( $input_value ); ?>"
            title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ); ?>"
            size="4"
            pattern="<?php echo esc_attr( $pattern ); ?>"
            inputmode="<?php echo esc_attr( $inputmode ); ?>"
            aria-labelledby="<?php echo esc_attr( $labelledby ); ?>" />
        <input type="button" value="+" class="quantity__button quantity__add js-qty-add" />
    </div>
</div>

My custom jQuery function:

function quantityButtons() {
    var $qtyAdd = $('.js-qty-add'),
        $qtyRemove = $('.js-qty-remove'),
        $qtyInput = $('.quantity__input');

    $qtyAdd.on('click', addQty);
    $qtyRemove.on('click', removeQty);

    function addQty() {
        var $qtyInput = $('.quantity__input'),
        $qtyRemove = $('.js-qty-remove'),
        $i = $qtyInput.val();

        $i++;
        $qtyRemove.attr("disabled", !$i);
        $qtyInput.val($i);
    }

    function removeQty() {
        var $qtyInput = $('.quantity__input'),
        $qtyRemove = $('.js-qty-remove'),
        $i = $qtyInput.val();

        if ($i >= 1) {
            $i--;
            $qtyInput.val($i);
        } else {
            $qtyRemove.attr("disabled", true);
        }
    }

    $qtyRemove.attr("disabled", !$qtyInput.val());
}

quantityButtons();
1

2 Answers 2

30

Your First code part is made from a customization of global/quantity-input.php Woocommerce template code…

So for testing, I have changed partially that global/quantity-input.php template code with the following (very near to your code):

?>
<div class="quantity">
    <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></label>
    <input type="button" value="-" class="qty_button minus" />
    <input
        type="number"
        id="<?php echo esc_attr( $input_id ); ?>"
        class="input-text qty text"
        step="<?php echo esc_attr( $step ); ?>"
        min="<?php echo esc_attr( $min_value ); ?>"
        max="<?php echo esc_attr( 0 < $max_value ? $max_value : '' ); ?>"
        name="<?php echo esc_attr( $input_name ); ?>"
        value="<?php echo esc_attr( $input_value ); ?>"
        title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ); ?>"
        size="4"
        pattern="<?php echo esc_attr( $pattern ); ?>"
        inputmode="<?php echo esc_attr( $inputmode ); ?>"
        aria-labelledby="<?php echo esc_attr( $labelledby ); ?>" />
    <input type="button" value="+" class="qty_button plus" />
</div>
<?php

Now the necessary CSS and revisited jQuery code functions:

// Minimum CSS to remove +/- default buttons on input field type number
add_action( 'wp_head' , 'custom_quantity_fields_css' );
function custom_quantity_fields_css(){
    ?>
    <style>
    .quantity input::-webkit-outer-spin-button,
    .quantity input::-webkit-inner-spin-button {
        display: none;
        margin: 0;
    }
    .quantity input.qty {
        appearance: textfield;
        -webkit-appearance: none;
        -moz-appearance: textfield;
    }
    </style>
    <?php
}


add_action( 'wp_footer' , 'custom_quantity_fields_script' );
function custom_quantity_fields_script(){
    ?>
    <script type='text/javascript'>
    jQuery( function( $ ) {
        if ( ! String.prototype.getDecimals ) {
            String.prototype.getDecimals = function() {
                var num = this,
                    match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
                if ( ! match ) {
                    return 0;
                }
                return Math.max( 0, ( match[1] ? match[1].length : 0 ) - ( match[2] ? +match[2] : 0 ) );
            }
        }
        // Quantity "plus" and "minus" buttons
        $( document.body ).on( 'click', '.plus, .minus', function() {
            var $qty        = $( this ).closest( '.quantity' ).find( '.qty'),
                currentVal  = parseFloat( $qty.val() ),
                max         = parseFloat( $qty.attr( 'max' ) ),
                min         = parseFloat( $qty.attr( 'min' ) ),
                step        = $qty.attr( 'step' );

            // Format values
            if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) currentVal = 0;
            if ( max === '' || max === 'NaN' ) max = '';
            if ( min === '' || min === 'NaN' ) min = 0;
            if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) step = 1;

            // Change the value
            if ( $( this ).is( '.plus' ) ) {
                if ( max && ( currentVal >= max ) ) {
                    $qty.val( max );
                } else {
                    $qty.val( ( currentVal + parseFloat( step )).toFixed( step.getDecimals() ) );
                }
            } else {
                if ( min && ( currentVal <= min ) ) {
                    $qty.val( min );
                } else if ( currentVal > 0 ) {
                    $qty.val( ( currentVal - parseFloat( step )).toFixed( step.getDecimals() ) );
                }
            }

            // Trigger change event
            $qty.trigger( 'change' );
        });
    });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

The quantity buttons "plus" and "minus" work perfectly and are displayed this way:

enter image description here

Products are added to cart with the correct quantity:

enter image description here

if you change the quantity field value with plus and minus buttons, the "Update cart" button is activated when any quantity field change.

enter image description here

When you click on "Update cart", the quantities as correctly updated.

3
  • 1
    Many thanks Loic, your code works great! I have seen similar jquery function in one of the wocommerce plugins, but I was not applying it correctly to my theme. Your detailed advice is very helpful! Thanks again!
    – Kai
    Commented Sep 18, 2018 at 15:13
  • It's working for me. Thanks for the answer. Upvote from my side. Commented Jan 26, 2021 at 15:55
  • @LoicTheAztec Could you take a look at this question please ? merci beaucoup stackoverflow.com/questions/67784840/… Commented Jun 14, 2021 at 22:39
2
/* Show Buttons */
add_action( 'woocommerce_before_add_to_cart_quantity', 'display_quantity_plus' );

function display_quantity_plus() {
     echo '<button type="button" class="plus" >+</button>';
}

add_action( 'woocommerce_after_add_to_cart_quantity', 'display_quantity_minus' );

function display_quantity_minus() {
     echo '<button type="button" class="minus" >-</button>';
}
//Note: to place minus @ left and plus @ right replace above add_actions with:
//add_action( 'woocommerce_before_add_to_cart_quantity', 'display_quantity_minus' );
//add_action( 'woocommerce_after_add_to_cart_quantity', 'display_quantity_plus' );

add_action( 'wp_footer', 'add_cart_quantity_plus_minus' );

function add_cart_quantity_plus_minus() {
 // Only run this on the single product page
 if ( ! is_product() ) return;
 ?>
  <script type="text/javascript">

  jQuery(document).ready(function($){   

     $('form.cart').on( 'click', 'button.plus, button.minus', function() {

        // Get current quantity values
        var qty = $( this ).closest( 'form.cart' ).find( '.qty' );
        var val   = parseFloat(qty.val());
        var max = parseFloat(qty.attr( 'max' ));
        var min = parseFloat(qty.attr( 'min' ));
        var step = parseFloat(qty.attr( 'step' ));

        // Change the value if plus or minus
        if ( $( this ).is( '.plus' ) ) {
           if ( max && ( max <= val ) ) {
              qty.val( max );
           } else {
              qty.val( val + step );
           }
        } else {
           if ( min && ( min >= val ) ) {
              qty.val( min );
           } else if ( val > 1 ) {
              qty.val( val - step );
           }
        }

     });

  });

  </script>

 //add css
 .single-product div.product form.cart .quantity {
      float: none;
      margin: 0;
      display: inline-block;
 }

Not the answer you're looking for? Browse other questions tagged or ask your own question.