javascriptshopify

Javascript radio button price change giving garbage answer


I've been busy working on a Shopify website page alongside a co-worker, who has tried to add radio buttons to change the output price on a purchasing page, however instead of adding to the base price, it just gives a garbage value as an output (the garbage value being & pound;0.00, when it should be adding £2 to the base price), I've looked at the script and I'm a bit stumped, the only indicated from Shopify being that newPrice in t: price: newPrice on line 17 is an unknown object.

Any pointers to a fix or better solution would be greatly appreciated.

<script>     
    var radioButtons = document.querySelectorAll('input[type="radio"]');
    var priceDisplay = document.querySelector('.product-price'); // Replace with your price element selector
    var basePrice = {{ product.price | money_without_currency }}; // Get the base price from Liquid

    radioButtons.forEach(function(button) {
      button.addEventListener('change', function() {
        var selectedValue = this.value;
        var newPrice = basePrice;

         if (selectedValue === 'without core drops') {
          newPrice = +0;  //Increase price by £0 for without core drops
        } else if (selectedValue === 'with core drops') {
          newPrice = +2;  //Increase price by £2 for with core drops
        } 

        priceDisplay.textContent = "{{ 'products.general.from' | t: price: newPrice | money }}";
      });
    });
</script>

Solution

  • You are now in the classic Liquid + JS hybrid situation, but your newPrice is breaking because of a keyconcept: Liquid runs at the server, but your newPrice is trying to be defined dynamically on client-side JavaScript.

    That is why price: newPrice display in Shopify as "unknown object".

    This means that the HTML is already rendered by Shopify Liquid, before the JS even executes. So when you try to use:

    priceDisplay.textContent = "{{ 'products.general.from' | t: price: newPrice | money }}";
    

    You need to handle the formatting fully in JavaScript, not Liquid.

      document.addEventListener('DOMContentLoaded', function () {
        var radioButtons = document.querySelectorAll('input[type="radio"]');
        var priceDisplay = document.querySelector('.product-price');
        var basePrice = {{ product.price | money_without_currency | remove: ',' }}; // Ensure no commas
    
        radioButtons.forEach(function (button) {
          button.addEventListener('change', function () {
            var selectedValue = this.value;
            var priceAdjustment = 0;
    
            if (selectedValue === 'without core drops') {
              priceAdjustment = 0;
            } else if (selectedValue === 'with core drops') {
              priceAdjustment = 2;
            }
    
            // Calculate new price
            var newPrice = parseFloat(basePrice) + priceAdjustment;
    
            // Format the price as currency (GBP)
            priceDisplay.textContent = new Intl.NumberFormat('en-GB', {
              style: 'currency',
              currency: 'GBP'
            }).format(newPrice);
          });
        });
      });