9

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?

starball
  • 20,030
  • 7
  • 43
  • 238
Peter Doro
  • 95
  • 1
  • 1
  • 5
  • I'd suggest including a link to the "answer by LoictheAztec" for reference. – Collin Barrett Jun 05 '18 at 16:40
  • I would link it to the actual website however it currently isn't live yet and is just being created in the wordpress dashboard. In order for others to view the site they would need the Username and Password. How would you recommend I get around this? – Peter Doro Jun 05 '18 at 19:02

2 Answers2

24

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.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • This works well except when the variation prices are all the same (I have a variable product that has color and size as variations but the price is the same.) after selecting the secon option the price disappears. – Ken Mar 14 '21 at 23:10
  • Hi there, has there been a breaking change to this by any chance? Likely, I'm just messing up something, but I would appreciate if you had a chance to look at it: Trying to set up this page: https://cinemastill.ethermedia.hu/product/1945/ next to the add to shopping button I have the prince range. I added the code functions.php, but nothing happens when I add the combination (100x50 + DOP has a price of 60 euros) – Pbalazs89 Apr 14 '21 at 11:50
2

To make it work with Woocommerce 3.8 you will need to replace the following line:

 $('select').blur( function(){

to

$('input.variation_id').change( function(){

Updated Code:

// Utility function to get the default variation (if it exist)
function get_default_variation( $product ){
    $attributes_count = count($product->get_variation_attributes());
    $default_attributes = $product->get_default_attributes();
    // If no default variation exist we exit
    if( $attributes_count != count($default_attributes) )
        return false;

    // Loop through available variations
    foreach( $product->get_available_variations() as $variation ){
        $found = true;
        // Loop through variation attributes
        foreach( $variation['attributes'] as $key => $value ){
            $taxonomy = str_replace( 'attribute_', '', $key );
            // Searching for a matching variation as default
            if( isset($default_attributes[$taxonomy]) && $default_attributes[$taxonomy] != $value ){
                $found = false;
                break;
            }
        }
        // If we get the default variation
        if( $found ) {
            $default_variaton = $variation;
            break;
        }
        // If not we continue
        else {
            continue;
        }
    }
    return isset($default_variaton) ? $default_variaton : false;
}

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 ) );
    $active_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 );
    $regular_price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );

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

    // When a default variation is set for the variable product
    if( get_default_variation( $product ) ) {
        $default_variaton = get_default_variation( $product );
        if( ! empty($default_variaton['price_html']) ){
            $price_html = $default_variaton['price_html'];
        } else {
            if ( ! $product->is_on_sale() )
                $price_html = $price = wc_price($default_variaton['display_price']);
            else
                $price_html = $price;
        }
        $availiability = $default_variaton['availability_html'];
    } else {
        $price_html = $price;
        $availiability = '';
    }
    // Styles ?>
    <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>
    <?php // Jquery ?>
    <script>
    jQuery(document).ready(function($) {
        var a = 'div.wc-availability', p = 'p.price';

        $('input.variation_id').change( function(){
            if( '' != $('input.variation_id').val() ){
                if($(a).html() != '' ) $(a).html('');
                $(p).html($('div.woocommerce-variation-price > span.price').html());
                $(a).html($('div.woocommerce-variation-availability').html());
            } else {
                if($(a).html() != '' ) $(a).html('');
                $(p).html($('div.hidden-variable-price').html());
            }
        });
    });
    </script>
    <?php

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

Hope it helps!

David García Bodego
  • 1,058
  • 3
  • 13
  • 21
Andre S
  • 49
  • 4
  • Hi, Your above code works perfectly. But on the archive or category page it still shows variable price range. Can you share how to show regular price cut off and show sale price on the products in archive or category page? Thank a lot for the above code.. – user2897282 Jul 03 '21 at 20:46