WooCommerce show custom stock message when a size variant is selected

38 views Asked by At

I have this logic on my product detail page: enter image description here

I've added this to the functions.php file for the active child theme:

// Enqueue JavaScript for handling variation change
add_action('wp_enqueue_scripts', 'custom_variation_stock_script');
function custom_variation_stock_script() {
    wp_enqueue_script('custom-variation-js', get_stylesheet_directory_uri() . '/js/custom-variation.js', array('jquery'), null, true);
}

// Add a placeholder for stock quantity display
add_action('woocommerce_single_product_summary', 'display_stock_quantity', 25);
function display_stock_quantity() {
    echo '<div id="stock_quantity_display" style="margin-bottom: 10px;"></div>';
}

custom-variation.js

jQuery(document).ready(function($) {
    $('form.variations_form').on('found_variation', function(event, variation) {
        console.error('CHECK VARIATION');
        if (variation.is_in_stock && variation.stock_quantity != null) {
            $('#stock_quantity_display').text('In stock: ' + variation.stock_quantity);
        } else {
            $('#stock_quantity_display').text('Out of stock');
        }
    }).on('reset_data', function() {
        $('#stock_quantity_display').text('');
    });
});

The code is executed when I change the dropdown, I see the error being logged. However, the element #stock_quantity_display is not inserted.

UPDATE 1

functions.php of child theme

<?php

function theme_enqueue_styles() {
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', [] );
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles', 20 );

function avada_lang_setup() {
    $lang = get_stylesheet_directory() . '/languages';
    load_child_theme_textdomain( 'Avada', $lang );
}
add_action( 'after_setup_theme', 'avada_lang_setup' );


add_action('wp_enqueue_scripts', 'custom_variation_stock_script');
function custom_variation_stock_script() {
    wp_enqueue_script('custom-variation-js', get_stylesheet_directory_uri() . '/js/custom-variation.js', array('jquery'), null, true);
}

//hide specific attributes from "Additional information tab" on Woo Tabs

add_filter( 'woocommerce_display_product_attributes', 'exclude_attribute_from_attribute_table', 9999, 2 );
function exclude_attribute_from_attribute_table( $product_attributes, $product ) {
   if ( isset( $product_attributes[ 'attribute_pa_ring-size' ] ) ) unset( $product_attributes[ 'attribute_pa_ring-size' ] );
   return $product_attributes;
}


// Add some extra variation data to the variable product form
add_filter( 'woocommerce_available_variation', 'add_product_variation_stock_quantity', 10, 3);
function add_product_variation_stock_quantity( $data, $product, $variation ) {
    return array_merge($data, array('stock_qty' => $variation->get_stock_quantity()));
}

// Add a placeholder for stock quantity display
add_action('woocommerce_single_product_summary', 'display_stock_quantity', 25);
function display_stock_quantity() {
    global $product;

    if ( !$product->is_type('variable') ) {
        return; // Exit if it's not a variable product
    }

    wc_enqueue_js("const a = '#stock_quantity_display';
    $('form.cart').on('show_variation', function( event, data ) {
        $(a).html(data.availability_html);
    }).on('hide_variation', function( event ) {
        $(a).html('');
    });");

    echo '<div id="stock_quantity_display" style="margin-bottom: 10px;"></div>';
}

custom-variation.js

jQuery(document).ready(function($) {
    console.error('CUSTOM JS');
    $('form.variations_form').on('show_variation', function(event, variation) {
        console.error('CHECK VARIATION');
        if (variation.is_in_stock && variation.stock_quantity != null) {
            $('#stock_quantity_display').text('In stock: ' + variation.stock_quantity);
        } else {
            $('#stock_quantity_display').text('Out of stock');
        }
    }).on('hide_variation', function() {
        $('#stock_quantity_display').text('');
    });
});

When I load the product detail page "CUSTOM JS" is logged to the console and when I change the product variation the line "CHECK VARIATION" is also logged.

However, when I right-click view source and look for element stock_quantity_display it's not there. How can I debug why the element is not injected?

1

There are 1 answers

6
LoicTheAztec On

There is no variation.stock_quantity defined, so you need to add it with:

// Add some extra variation data to the variable product form
add_filter( 'woocommerce_available_variation', 'add_product_variation_stock_quantity', 10, 3);
function add_product_variation_stock_quantity( $data, $product, $variation ) {
    return array_merge($data, array('stock_qty' => $variation->get_stock_quantity()));
}

Also, in your jQuery code use show_variation and hide_variation instead of found_variation and reset_data.

Now your code can be optimized in a unique function that will replace all your code:

// Add a placeholder for stock quantity display
add_action('woocommerce_single_product_summary', 'display_stock_quantity', 25);
function display_stock_quantity() {
    global $product;

    if ( !$product->is_type('variable') ) {
        return; // Exit if it's not a variable product
    }

    $instock_txt = __('In stock:', 'woocommerce');
    $outofstock_txt = __('Out of stock', 'woocommerce');

    wc_enqueue_js("const a = '#stock_quantity_display';
    $('form.cart').on('show_variation', function( event, data ) {
        const q = data.stock_qty;
        if (data.is_in_stock && q != null) {
            $(a).html('{$instock_txt} '+q);
        } else {
            $(a).html('{$outofstock_txt}');
        }
    }).on('hide_variation', function( event ) {
        $(a).html('');
    });");

    echo '<div id="stock_quantity_display" style="margin-bottom: 10px;"></div>';
}

Code goes in functions.php file of your child theme (or in a plugin). Tested and works.


Now you could use the built-in WooCommerce product availability instead like, replacing all previous code with the following:

// Add a placeholder for stock quantity display
add_action('woocommerce_single_product_summary', 'display_stock_quantity', 25);
function display_stock_quantity() {
    global $product;

    if ( !$product->is_type('variable') ) {
        return; // Exit if it's not a variable product
    }

    wc_enqueue_js("const a = '#stock_quantity_display';
    $('form.cart').on('show_variation', function( event, data ) {
        $(a).html(data.availability_html);
    }).on('hide_variation', function( event ) {
        $(a).html('');
    });");

    echo '<div id="stock_quantity_display" style="margin-bottom: 10px;"></div>';
}

Code goes in functions.php file of your child theme (or in a plugin). Tested and works.