I'm trying to create a custom button for products that have variations in WooCommerce.
For context, In WooCommerce, I have a product attribute called "License Type". This attribute has 2 terms:
I have a product (with an ID
of 203
), which contains these two variations:
In my theme, I have an override for content-single.product.php
template, where I have the following snippets:
select
dropdown for a user to determine which license they want:<?php
global $product;
if ($product->is_type('variable')) :
$taxonomy = 'pa_license_type';
$terms = array();
foreach ($product->get_children() as $variation_id) :
$variation = wc_get_product($variation_id);
if (!$variation) :
continue;
endif;
// Get the attribute value for the specified taxonomy
$attribute_value = $variation->get_attribute($taxonomy);
if ($term = get_term_by('slug', esc_html($attribute_value), $taxonomy)) :
$terms[$variation->get_id()] = $term;
endif;
endforeach;
if (count($terms) > 0) :
printf('<label for="%s">%s</label><select name="%s" id="%s">', esc_attr($taxonomy), wc_attribute_label($taxonomy), esc_attr($taxonomy), esc_attr($taxonomy));
foreach ($terms as $variation_id => $term) :
printf('<option value="%s" data-variation-id="%d">%s</option>', esc_attr($term->slug), $variation_id, esc_html($term->name));
endforeach;
echo '</select>';
endif;
endif;
?>
<?php if ( $product && $product->is_in_stock() ) :
$product_id = $product->get_id();
$add_to_cart_url = esc_url( '?add-to-cart=' . $product_id . '&redirect_to_cart=1' );
if ($product->is_type('variable')) : ?>
<a id="variationBtn" href="<?= $add_to_cart_url; ?>">
<?php _e( 'Add to Cart (Variation)', 'woocommerce' ); ?>
</a>
<?php else: ?>
<a href="<?= $add_to_cart_url; ?>">
<?php _e( 'Add to Cart', 'woocommerce' ); ?>
</a>
<?php endif; ?>
<?php endif; ?>
document.addEventListener('DOMContentLoaded', function() {
const variationBtn = document.getElementById('variationBtn');
const licenseTypeSelect = document.getElementById('pa_license_type');
function updateAddToCartUrl() {
const selectedOption = licenseTypeSelect.options[licenseTypeSelect.selectedIndex];
const selectedLicenseType = selectedOption.value;
const variationId = selectedOption.getAttribute('data-variation-id');
const addToCartUrl = `?add-to-cart=<?php echo $product_id; ?>&variation_id=${variationId}&attribute_pa_license-type=${selectedLicenseType}&redirect_to_cart=1`;
variationBtn.setAttribute('href', addToCartUrl);
}
// Init on page load with default values
updateAddToCartUrl();
// Update the URL when the license type changes
licenseTypeSelect.addEventListener('change', updateAddToCartUrl);
});
E.g A sample rendered HTML view of my button:
<a id="variationBtn" href="?add-to-cart=203&variation_id=211&attribute_pa_license-type=single-site-license&redirect_to_cart=1">Add to Cart (Variation)</a>
The desired functionality
The current results
Step 3 is where my approach isn't working.
My button href successfully updates with the variation ID on change etc. But, on click of the button, it doesn't add my product to the cart.
First, there are some small changes to make in your 2nd code snippet:
<?php if ( $product && $product->is_in_stock() ) :
$product_id = $product->get_id();
$add_to_cart_url = esc_url( '?add-to-cart=' . $product_id . '&redirect_to_cart=1' );
if ($product->is_type('variable')) {
printf('<a id="variationBtn" data-product_id="%d" href="%s">%s</a>', $product_id, $add_to_cart_url, __('Add to Cart (Variation)', 'woocommerce'));
} else {
printf('<a href="%s">%s</a>', $add_to_cart_url, __('Add to Cart', 'woocommerce') );
} ?>
<?php endif;?>
Then there are multiple mistakes in your JavaScript code (here I use jQuery as this JS library is used by WordPress and WooCommerce). Try the following instead:
jQuery(function($){
if ( $('#variationBtn').length ) {
const taxonomy = 'pa_license_type',
productID = $('#variationBtn').data('product_id');
var variationID = $('select[name='+taxonomy+']').find(":selected").data('variation-id'),
selectedVal = $('select[name='+taxonomy+']').find(":selected").val();
function changeAddToCartURL(){
const addToCartUrl = '?add-to-cart='+productID+'&variation_id='+variationID+'&attribute_'+taxonomy+'='+selectedVal+'&redirect_to_cart=1';
$('#variationBtn').attr('href', addToCartUrl);
}
// At start
changeAddToCartURL();
// On Change
$('select[name='+taxonomy+']').on('change', function(){
variationID = $(this).find(":selected").data('variation-id'),
selectedVal = $(this).find(":selected").val();
changeAddToCartURL();
});
}
});
Now you will be able adding to cart the selected variation (license type).