Search code examples
phpjquerywordpresswoocommerceproduct-variations

Display the calculated subtotal based on quantity in WooCommerce single variable products


I found the following code, that calculates the subtotal based on quantity for WooCommerce single products:

add_action( 'woocommerce_after_add_to_cart_button', 'bbloomer_product_price_recalculate' );
function bbloomer_product_price_recalculate() {
   global $product;
   echo '<div id="subtot" style="display:inline-block;">Total: <span></span></div>';
   $price = $product->get_price();
   $currency = get_woocommerce_currency_symbol();
   wc_enqueue_js( "     
      $('[name=quantity]').on('input change', function() { 
         var qty = $(this).val();
         var price = '" . esc_js( $price ) . "';
         var price_string = (price*qty).toFixed(2);
         $('#subtot > span').html('" . esc_js( $currency ) . "'+price_string);
      }).change();
   " );
}

However, it only works for simple products, but not for the product variations on variable products. I need assistance in modifying the code to accurately calculate the subtotal for variant products as well.

below, I have make some changes to the code, to handle the selected product variation for variable products:

add_action( 'woocommerce_after_add_to_cart_button', 'bbloomer_product_price_recalculate' );
function bbloomer_product_price_recalculate() {
   global $product;

   // Check if the product is variable or not
   if ( $product->is_type( 'variable' ) ) {
       // For variable products, get the default variation price
       $default_variation = $product->get_default_attributes();
       $variation_id = $product->get_matching_variation( $default_variation );
       $variation = wc_get_product( $variation_id );
       $price = $variation->get_price();
   } else {
       // For simple products, get the regular price
       $price = $product->get_price();
   }

   echo '<div id="subtot" style="display:inline-block;">Total: <span></span></div>';
   $currency = get_woocommerce_currency_symbol();
   wc_enqueue_js( "     
      $('[name=quantity]').on('input change', function() { 
         var qty = $(this).val();
         var price = '" . esc_js( $price ) . "';
         var price_string = (price*qty).toFixed(2);
         $('#subtot > span').html('" . esc_js( $currency ) . "'+price_string);
      }).change();
   " );
}

But it's not working. How to make it work for variable products too?


Solution

  • To display the formatted product subtotal for simple and variable products use the following:

    add_action( 'woocommerce_after_add_to_cart_button', 'display_product_subtotal_html' );
    function display_product_subtotal_html() {
        global $product;
    
        $price    = wc_get_price_to_display( $product );
        $currency = get_woocommerce_currency_symbol();
        $variable = $product->is_type('variable');
    
        echo '<div id="subtot" style="display:inline-block;">Total: <span></span></div>';
    
        if ( $product->is_type('variable') )
        wc_enqueue_js("var qty = 1, price = 0, subtotal = 0;  
        $('[name=quantity]').on('input change', function() { 
            qty = $(this).val();
            if ( price > 0 ) {
                subtotal = price*qty;
                $('#subtot > span').html('".esc_js($currency)." '+subtotal.toFixed(2));
            } else {
                $('#subtot > span').html('');
            }
        });
    
        $('form.variations_form').on('show_variation', function(event, data){
            price = data.display_price;
            subtotal = price*qty;
            $('#subtot > span').html('".esc_js($currency)." '+subtotal.toFixed(2));
        }).on('hide_variation', function(){
            $('#subtot > span').html('');
        });");
        else
        wc_enqueue_js("const price = ".floatval($price).";
        var subtotal = $('[name=quantity]').val()*price;
        $('#subtot > span').html('".esc_js($currency)." '+subtotal.toFixed(2));
    
        $('[name=quantity]').on('input change', function() { 
            subtotal = $(this).val()*price;
            $('#subtot > span').html('".esc_js($currency)." '+subtotal.toFixed(2));
        });");
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.