Woocommerce Product Variation Description with dynamic loading

Recently I had a project where a client needed to offer a variable product with extra information about each variation displayed, and this needed to change as the selector changed the variation. The product page would be linked to from another page on their site, with the desired variation pre-loaded in the drop-down selector on arrival. However, once there you could of course play with the drop-down to select other variations.

Let’s break down what I did to get everything working.

Here’s a quick summary:

  • create a textarea that gets added to the variations editor in the Woocommerce product
  • hook it in properly so it responds to javascript and normal page loading
  • get the contents of the textareas and inject them into the product page on the front end
  • hide all of them except the one we want to show based on the drop-down selector

The variable product custom field text area:

First, I wanted to create a textarea for each product variation for the client to be able to enter a description. Originally, I simply grabbed a plugin that did just that. But after we had a bunch of nightmares with malware and site hacking, we wiped everything and started over on a new host where we wanted to stay as clean as possible, limit our plugins, and by then that plugin had been removed from the repository. I found great instruction on adding custom fields to variable products by Remi Corson which looked easy to implement. Using his post as a guide I added a function to create the textarea and hook in properly to Woocommerce. And, as he points out, we have to deal with the Ajax creation of new variations, so everything is done twice as you’ll see. This goes in the functions file.


//Product Variation Description

//Display Fields
add_action( 'woocommerce_product_after_variable_attributes', 'variable_fields', 10, 3 );
//JS to add fields for new variations
add_action( 'woocommerce_product_after_variable_attributes_js', 'variable_fields_js' );
//Save variation fields
add_action( 'woocommerce_process_product_meta_variable', 'save_variable_fields', 10, 1 );

//Create new fields for variations
function variable_fields( $loop, $variation_data, $variation ) {
?>
 <tr>
  <td>
   <?php
   // Textarea
   woocommerce_wp_textarea_input(
    array(
     'id'          => '_textarea['.$loop.']',
     'label'       => __( 'Description', 'woocommerce' ),
     'placeholder' => '',
     'value'       => get_post_meta( $variation->ID, '_textarea', true ),
    )
   );
?>
 </td>
  </tr>
   <?php
}

// Create new fields for new variations
function variable_fields_js() {
?>
 <tr>
  <td>
   <?php
   // Textarea
   woocommerce_wp_textarea_input(
    array(
     'id'          => '_textarea[ + loop + ]',
     'label'       => __( 'Description', 'woocommerce' ),
     'placeholder' => '',
     'value'       => '',
    )
   );
?>
  </td>
 </tr>
<?php
}

//Save new fields for variations
function save_variable_fields( $post_id ) {
 if (isset( $_POST['variable_sku'] ) ) :
  $variable_sku          = $_POST['variable_sku'];
  $variable_post_id      = $_POST['variable_post_id'];
  // Textarea
  $_textarea = $_POST['_textarea'];
  for ( $i = 0; $i < sizeof( $variable_sku ); $i++ ) :
   $variation_id = (int) $variable_post_id[$i];
    if ( isset( $_textarea[$i] ) ) {
     update_post_meta( $variation_id, '_textarea', stripslashes( $_textarea[$i] ) );
    }
  endfor;
 endif;
}

The code gave me this in my variable products:

variable-descriptions

Get the Description to use on the Product Page:

To get the description I had created for them and add it to the product page, I’m using the all-powerful get_post_meta, and also grabbing the price, since they are all different. I’m doing this from the functions file and hooking in to the ‘before add to cart’ in Woocommerce. As you’ll notice this is going to write them all out on the page, which is not what we want, but I added some javascript to hide them all, then turn on each one depending on what’s selected in the drop-down. This also goes in the functions file.


function my_theme_function_woocommerce_before_add_to_cart_form() {
 // get the product
 global $product;
 // Get the post IDs of all the product variations
 $variation_ids = $product->children;
 // check if we have variations
 if ( empty( $variation_ids ) )
  return;
 // walk the variations
 foreach( $variation_ids as $variation_id ) {
  $variable_product= new WC_Product_Variation( $variation_id );
  $description = get_post_meta($variation_id, '_textarea');
  $price = $variable_product ->regular_price;
  echo '<div id="variation-' . $variation_id . '" style="display: none;" class="camp-description">';
  echo '<p>'.$description[0].'</p>';
  echo '<b> $'.$price.'</b>';
  echo '</div>';
 }
}
add_action( 'woocommerce_before_add_to_cart_form', 'my_theme_function_woocommerce_before_add_to_cart_form', 5 );

jQuery to show the one we want:

I needed this solution fast, so I resorted to some jQuery trickery to display the one description we want out of all the descriptions hidden on the page, based on what option was selected in the drop-down. This goes in a custom.js file that adds various extra jQuery I need on the site. It should be wrapped in the usual ‘jQuery(document).ready(function ($) {}’.


//Summer Camp products get variation ID to show/hide descriptions
setTimeout(function(){
 variationid= '';
 if(typeof $('input[name=variation_id]').val()  != "undefined" && $('input[name=variation_id]').val() !== null) {
  variationid = $('input[name=variation_id]').val();
  $('div#variation-'+variationid).show();
 }
}, 100);

setTimeout(function(){
 $('body').on('change', '#camps',function(){
  $('div#variation-'+variationid).hide();
  setTimeout(function(){
  variationid = $('input[name="variation_id"]').val();
  $('div#variation-'+variationid).show();
  }, 100)
 });
}, 200);

SIDE NOTE: to land on the page in the first place the user is clicking through from another page. The link they click is set up to leverage Woocommerce pre-filling the drop-down with a certain variation. The href in the link looks like this:

/summer-camp-registration/?attribute_camps=early-childhood-session-1-latin-celebrations

 Wrap up:

I’m sure there are some more elegant ways to do things, but this got me what I needed in a hurry, and seems to be working fine. I’m not crazy about having the timeouts in the js to allow for all the other Woocommerce js to work, but again it’s not too much of a drag on the user experience I think. If I get time I’ll go through more explanation of how things work on here. Here is the product page where you can see this working: https://www.waldorfsandiego.org/summer-camp-registration/?attribute_camps=early-childhood-session-1-latin-celebrations

4 thoughts on “Woocommerce Product Variation Description with dynamic loading

  1. hi mick,

    very interesting post, good job 🙂
    anyway, currently i am using wordpress 4.3 and woocommerce 2.4
    what all i need just want to get the product variation ID inside my cart items.
    could you help me by showing the simple code to get the variation ID ?
    thank you in advance for everything.

    /*following below is my code to validate minimum order using Product ID*/

    add_action( ‘woocommerce_check_cart_items’, ‘validasi_pembelian’ );

    function validasi_pembelian()
    {
    if( is_cart() || is_checkout() )
    {
    global $woocommerce;

    // Product Id and Min. Quantities per Product
    $product_min_qty = array(
    array( ‘id’ => 390, ‘min’ => 5 ),/*ipau kecil*/
    array( ‘id’ => 391, ‘min’ => 3 ),/*ipau sedang*/
    array( ‘id’ => 392, ‘min’ => 2 ),/*ipau besar*/ );

    // Will increment
    $i = 0;
    // Will hold information about products that have not
    // met the minimum order quantity
    $bad_products = array();

    // Loop through the products in the Cart
    foreach( $woocommerce->cart->cart_contents as $product_in_cart ) {
    // Loop through our minimum order quantities per product
    foreach( $product_min_qty as $product_to_test ) {
    // If we can match the product ID to the ID set on the minimum required array
    if( $product_to_test[‘id’] == $product_in_cart[‘product_id’] ) {
    // If the quantity required is less than than the quantity in the cart now
    if( $product_in_cart[‘quantity’] < $product_to_test['min'] ) {
    // Get the product ID
    $bad_products[$i]['id'] = $product_in_cart['product_id'];
    // Get the Product quantity already in the cart for this product
    $bad_products[$i]['in_cart'] = $product_in_cart['quantity'];
    // Get the minimum required for this product
    $bad_products[$i]['min_req'] = $product_to_test['min'];
    }
    }
    }
    // Increment $i
    $i++;
    }
    }
    }

  2. This code seems to be broken with the latest update to WooCommerce (2.6.1). I now have a Fatal error message and my product variations don’t show.

    https://www.imagingexpressionskc.com/product/ready-made-board-collection/

    Fatal error: Uncaught exception ‘Exception’ with message ‘No parent product set for variation #1’ in /home/imagingexpress/public_html/wp-content/plugins/woocommerce/includes/class-wc-product-variation.php:85 Stack trace: #0 /home/imagingexpress/public_html/wp-content/themes/ImagingExpressions/functions.php(248): WC_Product_Variation->__construct(Array) #1 [internal function]: my_theme_function_woocommerce_before_add_to_cart_form(”) #2 /home/imagingexpress/public_html/wp-includes/plugin.php(525): call_user_func_array(‘my_theme_functi…’, Array) #3 /home/imagingexpress/public_html/wp-content/plugins/woocommerce/templates/single-product/add-to-cart/variable.php(26): do_action(‘woocommerce_bef…’) #4 /home/imagingexpress/public_html/wp-content/plugins/woocommerce/includes/wc-core-functions.php(203): include(‘/home/imagingex…’) #5 /home/imagingexpress/public_html/wp-content/plugins/woocommerce/includes/wc-template-functions.php(981): wc_get_template(‘single-product/…’, Array) #6 [internal function]: woocommerce_variable in /home/imagingexpress/public_html/wp-content/plugins/woocommerce/includes/class-wc-product-variation.php on line 85

    1. Cody- I haven’t been able to get ahead enough on work and family to dig back into this problem. As soon as I get a break I’ll see if I have any insight.

  3. Hi , can any one help me
    i have a page where i am showing my product using woocommerce product shortcode like this [product_page id=”137″],
    this is a variable product with two attribute , city and date ,
    after selecting city and date i want to change my all page content . how can i do this pls help

    thanks in advance

Leave a Reply

Your email address will not be published. Required fields are marked *