I am trying to add custom fields to my WooCommerce site to update the price based on the warranty status selected by the customer when choosing a product variation. Specifically, I want the price to adjust according to whether the warranty is expired, within 1-6 months, over 6 months, or unactivated.
I have implemented the following code, which correctly displays the warranty options and the adjusted price on the page. However, the price does not update correctly when changing variations, leading to calculation errors. Here’s my code:
add_action('woocommerce_single_variation', 'add_custom_options', 5);
function add_custom_options() {
?>
<div class="custom-options-wrapper" style="width: 100%;">
<h4>Great, let's talk about the more details:</h4>
<div class="custom-warranty-option" style="margin-bottom: 20px;">
<label>1. Is it still under warranty?</label>
<label style="display: block;">
<input type="radio" name="warranty_status" value="no" required> No, the warranty has expired.
</label>
<label style="display: block;">
<input type="radio" name="warranty_status" value="1-6months" required> Yes, 1-6 months warranty
</label>
<label style="display: block;">
<input type="radio" name="warranty_status" value="over6months" required> Yes, over 6 months warranty
</label>
<label style="display: block;">
<input type="radio" name="warranty_status" value="unactivated" required> Yes, 1 year warranty & unactivated
</label>
</div>
</div>
<script type="text/javascript">
jQuery(document).ready(function($) {
var originalPrice;
function getOriginalPrice() {
var priceText = $('.woocommerce-variation-price .woocommerce-Price-amount.amount').first().text();
return parseFloat(priceText.replace(/[^d.]/g, ''));
}
function updatePrice() {
if (isNaN(originalPrice)) {
originalPrice = getOriginalPrice();
}
var warrantyMultiplier = 1.00;
if ($('input[name="warranty_status"]:checked').val() === 'no') {
warrantyMultiplier = 0.90; // No warranty, deduct 10%
} else if ($('input[name="warranty_status"]:checked').val() === '1-6months') {
warrantyMultiplier = 0.92; // 1-6 months warranty, deduct 8%
} else if ($('input[name="warranty_status"]:checked').val() === 'over6months') {
warrantyMultiplier = 0.95; // Over 6 months warranty, deduct 5%
}
var newPrice = Math.round(originalPrice * warrantyMultiplier);
$('.woocommerce-variation-price .woocommerce-Price-amount.amount').html('<bdi><span class="woocommerce-Price-currencySymbol">$</span>' + newPrice + '</bdi>');
// Update hidden input to ensure the new price is used when added to the cart
$('#custom_price').val(newPrice);
}
// Clear the selected state of all custom options
function resetCustomOptions() {
$('input[name="warranty_status"]').prop('checked', false);
}
$('form.variations_form').on('woocommerce_variation_has_changed', function() {
resetCustomOptions(); // Reset custom options
originalPrice = getOriginalPrice(); // Get new price each time a variation is switched
updatePrice();
});
$('input[name="warranty_status"]').change(function() {
updatePrice();
});
originalPrice = getOriginalPrice();
updatePrice();
});
</script>
<?php
}
Main Issue: When a user switches between variations, the price does not correctly update based on the selected warranty status. How can I ensure the price is recalculated and updated when the variation changes?
I would appreciate any suggestions to resolve this issue! Thank you!
2
Answers
First, it is better to include the variations warranty prices HTML to the variable product data form. Then you should use WooCommerce variation JS events to change your prices.
Try the following revised code:
Code goes in functions.php file of your child theme (or in a plugin).
Now it will work without any issue.
Addition:
Reset the Warranty selected option on selected variation change
To reset the Warranty selected option on selected variation change, you can change the JavaScript code block inside the 2nd function like:
It looks like the main issue you’re facing is that the
originalPrice
value doesn’t get updated properly when switching between product variations. This can happen if theoriginalPrice
variable holds onto an old value, leading to incorrect price calculations.To address this, let’s make sure we:
Properly retrieve and reset the
originalPrice
every time a variation changes.Ensure the custom price is reset when switching variations to avoid conflicts.
By setting
originalPrice
to null when a variation changes, we ensure the original price is fetched from the updated variation. TheresetCustomOptions()
function now clears the previously selected warranty option each time a variation is changed.ThegetOriginalPrice()
function is called on every variation change to ensure the correct base price is used.Make sure to add a hidden input field with the ID
custom_price
if you need to pass the updated price to the WooCommerce cart.If you encounter rounding issues, you might want to use
toFixed(2)
onnewPrice
to format it correctly.Feel free to leave a comment on the solution, I’ll surely share my thoughts on that.