Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable product selectors: Getting the live selected values

In WooCommerce use the code below to add a custom label after product prices in simple and variables products:

add_filter('woocommerce_variation_price_html','prices_custom_labels', 10, 2    );
add_filter('woocommerce_price_html','prices_custom_labels', 10, 2 );
function prices_custom_labels( $price, $product ){

    // Set HERE your custom labels names
    $per_dozen = ' '. __('per dozen', 'woocommerce' );
    $per_case = ' '. __('per case (20 dozens)', 'woocommerce' );


    // 1) Variable products
    if ($product->product_type != 'simple' && $product->variation_id ) {

        // Getting the array of existing attributes values for a variation
        $variation_attribute_value = $product->variation_data;
        // Here we keep only the last value in this array
        $last_variation_attribute_slug_value = ' ' .    end($variation_attribute_value);

        // Finding the word 'case' in the attribute value slug
        $has_case = strstr($last_variation_attribute_slug_value, 'case');

        // Setting the right displayed label depending on attribute value slug
        if( $has_case )
            $attribute_quantity_name_value = $per_case;
        else
            $attribute_quantity_name_value = $per_dozen;

        // Here the output price + custom label
        $price = '<ins class="highlight">'.woocommerce_price( $product-   >regular_price ).$attribute_quantity_name_value.'</ins>';
    }
    // 2) Simple products
    else
    {
        // Here the output price + custom default label
        $price = '<ins class="highlight">'.woocommerce_price( $product-  >regular_price ).$per_dozen.'</ins>';
    }
    return $price;
}

But in variable products, I have an issue with the appended custom label in the live displayed price. The code that I use only display after the live price "per dozen".

I will need to get the selected value on the custom "quantity" selector to add the right label after the price:

  • If the selected value is "Dozen" I need to display after live price " per dozen",
  • If the selected value is "Case (20 dozens)" I need to display after live price " per case (20 dozens)".

This screenshot is what I have actually for all cases:

enter image description here

Check this issue on my web site specific product page

So I would need to get the attribute "quantity" selected value to append the right label to the live price.

What can I do to get that working?

like image 453
Dora Avatar asked Feb 05 '23 01:02

Dora


1 Answers

The only way to get this working is to use Javascript / jQuery, but it's complicated as WooCommerce is already running some Javascript / Ajax code on it.

First, Is not possible to detect the selected customer choice on the selectors as WooCommerce remove "selected" attribute from <option> html tags.

Once customer have make a complete selection (so choosed one variation from this variable product), Woocommerce add the corresponding variation ID value in a hidden <imput> html field and display the corresponding price.

Our PHP code pass to javascript an array of the variations IDs for this variable product, with the corresponding value of the "quantity" attribute for each of them.

Then we can use the "on blur" javascript event on the <select> html tags to get that hidden variation ID value and then append the price with the right "label".

Here is that functional code, that will add a custom label to the live price depending on the customer selection (so the selected product variation):

add_action( 'woocommerce_after_add_to_cart_form', 'custom_get_variations_js' );
function custom_get_variations_js() {
    global $product;

    // Set HERE your "quantity" attribute slug
    $attribute_qty_slug = 'pa_quantity';
    $attribute_qty_slug_key = 'attribute_'.$attribute_qty_slug;

    foreach($product->get_available_variations() as $values){
        $attribute_qty_slug_value = $values['attributes'][$attribute_qty_slug_key];
        $attribute_qty_name_value = get_term_by( 'slug', $attribute_qty_slug_value, $attribute_qty_slug );
        $variations_id_arr[$values['variation_id']] = __(' per ', 'woocommerce' ) . strtolower($attribute_qty_name_value->name);
    }

    ## THE JQUERY SCRIPT ##
    ?>
    <script>
        (function($){
            var $attributes;
            <?php
                // Passing the product variations attributes array to javascript
                $js_array = json_encode($variations_id_arr);
                echo 'var $variationsIdsAttr = '. $js_array ;
            ?>
            $('td.value select').blur(function() {
                var $variationId = $('input[name="variation_id"]').val();
                if (typeof $variationId !== 'undefined' ){
                    for(key in $variationsIdsAttr){
                        if( key == $variationId ){
                            $attributes = $variationsIdsAttr[key];
                            break;
                        }
                    }
                }
                if ( typeof $attributes !== 'undefined' ){
                    $('.woocommerce-variation-price .woocommerce-Price-amount.amount').append( $attributes );
                }
            });
        })(jQuery);
    </script>
    <?php
}

Then we need to change your existing code to avoid displaying a second custom label on this specifics variable products (in the first hooked function):

add_filter('woocommerce_variation_price_html','prices_custom_labels', 10, 2 );
add_filter('woocommerce_price_html','prices_custom_labels', 10, 2 );
function prices_custom_labels( $price, $product ){

    // Custom label name
    $per_dozen = ' '. __('per dozen', 'woocommerce' );

    // Set HERE your "quantity" attribute slug
    $attribute_qty_slug = 'pa_quantity';

    $attribute_qty_slug_key = 'attribute_'.$attribute_qty_slug;
    $append_label = '';

    // 1) Variable products
    if ($product->product_type != 'simple' && $product->variation_id ) {

        // Getting the attribute "quantity" value
        $attribute_qty_is_set = $product->variation_data[$attribute_qty_slug_key];
        echo '<pre>'; print_r($product->variation_data[$attribute_qty_slug_key]); echo '</pre>';

        // if "quantity" not set we display " per dozen"
        if( ! $attribute_qty_is_set )
            $append_label = $per_dozen;


        // Outputed price + custom label
        $price = '<ins class="highlight">'.woocommerce_price( $product->regular_price ).$append_label.'</ins>';
    }
    // 2) Simple products
    else
    {
        // Here the output price + custom default label
        $price = '<ins class="highlight">'.woocommerce_price( $product->regular_price ).$per_dozen.'</ins>';
    }
    return $price;
}

add_filter('woocommerce_variable_price_html', 'prices_custom_labels_min_max', 20, 2);
function prices_custom_labels_min_max( $price, $product) {

    // Custom label name
    $per_dozen = ' '. __('per dozen', 'woocommerce' );
    $per_case = ' '. __('per case', 'woocommerce' );

    // Set HERE your quantity attribute slug
    $attribute_qty_slug = 'pa_quantity';


    // Getting the min and max variations prices
    $variation_min_reg_price = $product->get_variation_regular_price('min', true);
    $variation_max_reg_price = $product->get_variation_regular_price('max', true);
    $variation_reg_price = $product->get_variation_regular_price();


    if( $variation_min_reg_price == $variation_max_reg_price )
    {
        $price = '<ins class="highlight">'.woocommerce_price($variation_reg_price) . $per_dozen . '</ins>';
    }
    else
    {
        if( !in_array( $attribute_qty_slug, array_keys( $product->get_attributes() ) ) )
        {
            $price = '<ins class="highlight">' . woocommerce_price($variation_min_reg_price) . $per_dozen . ' - ' . woocommerce_price($variation_max_reg_price) . $per_dozen . '</ins>';
        }
        else
        {
            $price = '<ins class="highlight">' . woocommerce_price($variation_min_reg_price) . $per_dozen . ' - ' . woocommerce_price($variation_max_reg_price) . $per_case . '</ins>';
        }
    }
    // print_r($product->get_attributes());
    return $price;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.


Related answer:

  • Pass the chosen product variations data into Contact Form 7 enquiry form
  • Adding custom text labels to the product prices depending on their type
like image 179
LoicTheAztec Avatar answered Feb 07 '23 19:02

LoicTheAztec