phpwordpresswoocommerceproduct-variations

Replace the Variable Price range by the chosen variation price in WooCommerce 4+


On our woocommerce website I am trying to update the displayed price based on the variations the customer selects from dropdown menus as shown here:

Example of dropdown variation selection

I used a php function that had been submitted in another answer by LoictheAztec:
https://stackoverflow.com/questions/44912300/replace-the-variable-price-range-by-the-chosen-variation-price-in-woocommerce-3

add_action( 'woocommerce_before_single_product', 'move_variations_single_price', 1 );
function move_variations_single_price(){
    global $product, $post;

    if ( $product->is_type( 'variable' ) ) {
        // removing the variations price for variable products
        remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );

        // Change location and inserting back the variations price
        add_action( 'woocommerce_single_product_summary', 'replace_variation_single_price', 10 );
    }
}

function replace_variation_single_price(){
    global $product;

    // Main Price
    $prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
    $price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );

    // Sale Price
    $prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
    sort( $prices );
    $saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );

    if ( $price !== $saleprice && $product->is_on_sale() ) {
        $price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
    }

    ?>
    <style>
        div.woocommerce-variation-price,
        div.woocommerce-variation-availability,
        div.hidden-variable-price {
            height: 0px !important;
            overflow:hidden;
            position:relative;
            line-height: 0px !important;
            font-size: 0% !important;
        }
    </style>
    <script>
    jQuery(document).ready(function($) {
        $('select').blur( function(){
            if( '' != $('input.variation_id').val() ){
                if($('p.availability'))
                    $('p.availability').remove();
                $('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
                console.log($('input.variation_id').val());
            } else {
                $('p.price').html($('div.hidden-variable-price').html());
                if($('p.availability'))
                    $('p.availability').remove();
                console.log('NULL');
            }
        });
    });
    </script>
    <?php

    echo '<p class="price">'.$price.'</p>
    <div class="hidden-variable-price" >'.$price.'</div>';
}

However when a variation is selected it displays undefined underneath the From: $price as shown here:

Example of undefined error:

Example of undefined error

What is the cause of this error and how can it be made so that the price is displayed and updated based on variations that have been selected?


Solution

  • Update March 2021 (Works at least from WooCommerce 3.7 up to 5+)

    The code:

    add_action('woocommerce_before_add_to_cart_form', 'selected_variation_price_replace_variable_price_range');
    function selected_variation_price_replace_variable_price_range(){
        global $product;
    
        if( $product->is_type('variable') ):
        ?><style> .woocommerce-variation-price {display:none;} </style>
        <script>
        jQuery(function($) {
            var p = 'p.price'
                q = $(p).html();
    
            $('form.cart').on('show_variation', function( event, data ) {
                if ( data.price_html ) {
                    $(p).html(data.price_html);
                }
            }).on('hide_variation', function( event ) {
                $(p).html(q);
            });
        });
        </script>
        <?php
        endif;
    }
    

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