WooCommerce reviews + tutorials

This is a quick little ‘how to’ that came up in a recent client WooCommerce request. The client wanted to add the text ‘sold out’ to the variable product configuration dropdowns on the product page to make it more clear to customers when a variation was out of stock:

woocommerce variation form - original
woocommerce variation form - modified

Requirements

In order for this to work, you have to be sure that your WooCommerce settings allow you to show out of stock products. Find the Out of stock visibility setting under WooCommerce > Settings > Products > Inventory, and be sure it’s disabled.

โš ๏ธ This tutorial assumes you have basic PHP development knowledge. Not sure how to add custom code to your site? Check out our tutorial for help. Need some help implementing or taking this code further? We recommend Codeable for small custom projects.

The Implementation

By default, WooCommerce will only tell your customers a variation is out of stock after that variation has been selected, showing an “Out of stock” notice above the add to cart button.

To modify the options themselves for this instead, we need to take two steps.

First, we’ll edit the option HTML to add a “sold out” text to the option. The woocommerce_variation_option_name filter is just what we need! It’s not super easy to use, though: you don’t have access to the variation object in that filter, only the parent product.

So, we’ll do a little bit of matching up to see if the option value matches one of that parent product’s variations, and if so, we’ll add our sold out text.

/**
 * Adds a "sold out" identifier to out of stock variations on product pages.
 *
 * @param string $option the option HTML
 * @param null $_ unused
 * @param string $attribute the option attribute
 * @param \WC_Product_Variable $product the parent product
 * @return string updated option HTML
 */
add_filter( 'woocommerce_variation_option_name', function( $option, $_, $attribute, $product ) {

	$sold_out_text = __( ' - sold out', 'my-textdomain' );
	$variations    = $product->get_available_variations();

	foreach ( $variations as $variation ) {

		if ( $variation['attributes']['attribute_value'] === $option && ! $variation['is_in_stock'] ) {
			$option .= $sold_out_text;
		}
	}

	return $option;

}, 1, 4 );

Now we’ll have a “sold out” identifier added to any variation options that are not in stock!

You can stop here if you’d like. ๐Ÿ™‚ We opted to keep going to also disable that option when the variation is sold out.

This was a bit more difficult to implement than you might imagine at first blush, because the product variation dropdowns are controlled by somewhat tricky JavaScript. The relevant JavaScript can be found in the file woocommerce/assets/js/add-to-cart-variation.js in an anonymous function callback which is invoked every time the page loads, or the variable product is configured by the user, and ensures that the correct product options are displayed, and enabled or disabled. Luckily for us this function fires a custom DOM event named woocommerce_update_variation_values, allowing us to listen to changes and manipulate the options to disable the one we want.

The JavaScript we need to inject into the page to add the ‘Sold Out’ (or any other notice) is the following:

<script>
$( document ).bind( 'woocommerce_update_variation_values', function() {
	$( '.variations select option' ).each( function( index, el ) {
		if ( el.text.includes( '- sold out' ) ) {
			$( this ).attr( 'disabled', true );
		}
	} );
} );
</script>

We need a hook to add this, though! I’m also going to ensure that the “sold out” text we look for matches the text from my previous function.

/**
 * Add JS to disable the sold out variation option.
 *  Be sure to keep the sold out text consistent with the woocommerce_variation_option_name callback.
 */
add_action( 'woocommerce_after_variations_form', function() {

	$sold_out_text = __( ' - sold out', 'my-textdomain' );

	ob_start();
	?>

$( document ).bind( 'woocommerce_update_variation_values', function() {
	$( '.variations select option' ).each( function( index, el ) {
		if ( el.text.includes( '<?php echo esc_js( $sold_out_text ); ?>' ) ) {
			$( this ).attr( 'disabled', true );
		}
	} );
} );

	<?php
	$js = ob_get_clean();

	wc_enqueue_js( $js );
	
} );

Now that JavaScript will run every time the variations are adjusted, ensuring that my “sold out” option is also disabled when shown in my dropdown.

woocommerce variation form - modified for sold out items

Published by Justin Stern

Justin is one of our co-founders, and is our resident overengineer. He likes to write developer tutorials and make black magic happen in our plugins. He thinks that writing code is a lot easier than writing words.

38 Comments

  1. GREAT JOB ! works perfectly! i simply insterted the code into my woocommerce-functions.php and worked perfectly!

  2. Works like a charm…thank you!

  3. hi

    is there a way to stop the variations from showing in the drop down menu when their stock value is 0

    i really need you help as the client want to launch this Friday and i can not find a way round

  4. THANK YOU! Worked like a charm.

  5. This isn’t working for me.

    I have the latest version of WooCommerce which is supposed to show the stock on the product page when a variation is selected.

    What’s strange is that when I look in variations.php, there seems to be no code which adds the disabled attribute to the options.

    if ( taxonomy_exists( sanitize_title( $name ) ) ) {

    $terms = get_terms( sanitize_title($name), array(‘menu_order’ => ‘ASC’) );

    foreach ( $terms as $term ) {

    if ( ! in_array( $term->slug, $options ) ) continue;

    echo ‘slug . ‘” ‘ . selected( $selected_value, $term->slug, false ) . ‘>’ . apply_filters( ‘woocommerce_variation_option_name’, $term->name ) . ”;

    }

    } else {

    foreach ( $options as $option )

    echo ” . apply_filters( ‘woocommerce_variation_option_name’, $option ) . ”;

    }

    • Hey Sebastien, I know that WooCommerce updated their variation handling javascript in a recent release, so I just tested my old solution out with the latest version of WooCommerce and it worked just fine. You’re correct in your observation that variations.php doesn’t disable any product variations. As I describe in the article, that’s part of what makes altering the variation handling code a little bit tricky: it’s all done with some complex JavaScript found within add-to-cart-variation.js, and so is implemented in the frontend, rather than in PHP code, which is a perfectly understandable place to start looking.

  6. Is it possible for me to achieve the same result without having hide the product on catalog page?

    • This particular example relies on that setting being enabled, it’s how the out of stock items are detected. That being said, almost anything can be done, it would just require a bunch more coding and a slightly different approach.

  7. what about if there are two options, say, size and color.

    I need a solution so if the BLUE MEDIUM shirt is not available… uses can still choose BLUE but when they go to choose SIZE MEDIUM will show as not avilable, but small and large will show as available

    doabale?

  8. Hello I am trying to get this to work.. it’s working somewhat.. the out of stock variables are greyed out but the text “sold out” is not showing up. Is there something that I missed?

  9. Thanks, Justin. I just started playing around with this and it works in most cases. However, I discovered there are reasons an item could be disabled besides being sold out, and then they get mislabeled.

    For example, let’s say you have a book for sale with a media type attribute having print or e-book options, and a language attribute having English or Spanish options. Both attributes are used for variations. But the Spanish version is only available as an e-book, so the print variation is left out.

    Then, if someone selects print in the media type drop-down menu, the language menu will show Spanish as disabled, which would then incorrectly get the sold out text added.

    I haven’t come up with a way yet to alter this behavior since we can’t tell why an item is disabled. Any ideas?

    • hmm, yeah good point. Honestly it may not even be possible to detect these sorts of cases, the javascript that handles this stuff is not the easiest to work with. It would take a bit of research and digging to determine

  10. Just what I needed for an upcoming project. thanks!

  11. Hi Justin!
    I can’t see the Javascript code of the first box:
    http://img35.imageshack.us/img35/1157/capturadepantalla201305ek.png
    I’ve tested in Safari and Chrome.
    Regards!

  12. hi all,

    I want to create a custom field for woocommerce product page in the backend and the front end.if the product is for sale then it should show all the details like add to cart and all.
    if the product is not for sold then it should just display the image and the simple text.Can Some one help me out soon please.

  13. Still can’t see the javascript box!

  14. Hi,
    I don’t know what I’m doing wrong but it’s not working for me.
    I’m using wordpress 3.5.1 with Woocommerce 2.0.5 and WPML 2.8.2

    As a result of having “hide out of stock items from catalog” checked I don’t see the items at all that I would like to appear with “sold out” markings.

    Similar to your example we have shoes that are in variable colours and sizes. So the stock control is on the product variations level.

    Thanks in advance!
    Patricia

    • Hey Patricia, try unchecking the “hide out of stock items” and seeing if that solves your issue.

  15. Woocommerce 2.0.10 and WordPress 3.5.1. I’m trying to add your code in my functions.php but nothing’s changed. I’m also unchecked the โ€œhide out of stock itemsโ€, and changed the selector on jQuery… nothing.
    Is “add_action( ‘woocommerce_before_add_to_cart_form’, ‘woocommerce_sold_out_dropdown’ );” still correct for new versions of plugin?

    • Hey Roberto, unfortunately this sample no longer works with the current version of woocommerce

  16. Would be really awesome if you could update this code or even make a plugin that would work. Such an extraordinarily useful feature. Have a look at Jack Will website too. They have little icons like S, M, L with X’s on top of them if they are sold out. Really convenient over having to select each option just to find out if a product is in stock.

  17. Hello Justin,

    I did see your note at the top of this blog post, regarding WooCommerce 2.x and how this code no longer works, so not sure it’s worth even messing with at this point.

    But I am encountering a different issue when it comes to “No Stock” variable items. Check the following page out as an example: http://www.sportsboxbreaks.com/product/basketball-test/

    So the “Blue” variation has 0 in stock, and if you choose that drop-down selection you will see the message displaying “Out of stock”. However, I have seen other WooCommerce installs do the “graying out” of a menu item, which effectively disables that menu item from being selected when that variation is out of stock. This is what your code above builds upon, with the adding of “sold out” to the disabled menu item.

    Is there a setting somewhere in WooCommerce Settings>Inventory, or in the Product Variation settings itself that enables the disabled “grayed out” menu item when the product variation is no longer in stock?

    For the life of me I can’t seem to figure out how to enable this, and it’s driving me a bit insane ๐Ÿ™‚ Any direction would be appreciated.

    • I think this is a theme-specific customization that probably requires some javascript manipulation to set the individual option as “disabled” which makes it appear greyed out. I’d look at the source code of the other installs where you’ve seen this done to get you started in the right direction ๐Ÿ™‚

  18. Hi Justin, I would like to know if your code is working with current WC 2.0.19 version. I sell items individually so buyers can not buy more than one particular item. I am looking to show item as SOLD after someone checked-out and paid for the item. In products quick Edit view, I can see a box with heading as “In Stock?”. Currently there are two options to choose from one is In Stock and other one is Out Of Stock. Is there a way I can add one more option which says “SOLD” ….One more question if you could help please. I want to show Make an Offer option with every product just like on eBay where buyer can make an offer. Thanks mate

    • Hey, this code no longer works with WC 2.0+. There’s not going to be an easy way to add a new stock option, but what you *can* do is have the “Out of Stock” label display as “SOLD” by adding the following snippet to the bottom of your theme’s functions.php:

      add_filter( 'woocommerce_get_availability', function( $return, $product ) {
        if ( 'out-of-stock' == $return['class'] ) {
          $return['availability'] = 'SOLD';
        }
        return $return;
      } );
      

      As far as a “make an offer”, there’s no off-the-shelf plugin that I’m aware of that provides that sort of functionality. The closest would probably be Name Your Price http://www.woocommerce.com/products/name-your-price/ which allows the customer to specify the price for the product and pay that amount and checkout, but I don’t know if that provides exactly the type of functionality you’re looking for, which sounds more like a bidding system.

  19. Hi Justin,
    I want to add following code
    REMOVE
    to my woocommerce cart page.
    Could you please guide me how to add this. Thanks

  20. How do I print a price for a product on a sold out Item?

  21. Any updates on this or any new fixes? This is exactly what I need to do right now.

Hmm, looks like this article is quite old! Its content may be outdated, so comments are now closed.