Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
I added "you save x%" using this code:
{% capture discount %} {{ current_variant.compare_at_price | minus: current_variant.price | money }} ({{ current_variant.compare_at_price | minus: current_variant.price | times: 100.0 | divided_by: current_variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%) {% endcapture %} You save: {{ discount }}
But I couldn't make it work when I have multiple variants.
Normally, it works on the first reload but how can I make it change when I selected different variant?
Help would be appreciated. Thank you.
Solved! Go to the solution
This is an accepted solution.
ok I'm back now, sorry bout the wait, aight so the issue is that your data-sale-price is controlled by a function within theme.js which changes the value based on the variant selected, Shopify's liquid isn't as good as Angular or React yet, basically, you can't double bind elements in order to refresh the data once it's loaded which is why liquid.... is far behind and sucks but that's life, so Javascript to the rescue.
On line 51, you'll find this
<span class="price-item price-item--sale" data-sale-price>
Doing a quick search through theme.js we can trace where the data is being changed and there we go, let's change the code a bit to have it render what we want. However before let's change the liquid a bit to this
<div class="price__sale"> <dd> <div class="price-item price-item--sale" data-sale-price> {{ money_price }} <div class="price-item price-item--sale--save">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span> </div> </dd> </div>
Basically, I remove the Sale string as it's no longer needed and moved the sale up.
In Theme.js
On line 3678 You should see this:
$salePrice.html( theme.Currency.formatMoney(variant.price, theme.moneyFormat) );
Change it to this
$salePrice.html( '<div class="price-item price-item--sale">' + theme.Currency.formatMoney(variant.price, theme.moneyFormat) + '<div class="price-item price-item--sale--save">You save: ' + theme.Currency.formatMoney(variant.compare_at_price - variant.price, theme.moneyFormat) + ' (' + Math.round((1 - (variant.price / variant.compare_at_price)) * 100) + '%) ' + '</div>' + '</div>' );
It could be refactored a bit with more elegant code but ES6 isn't compatible with most older browsers which represent 5-15% of your sales, unless you installed a polyfill library like babel.js
Voila, it works now.
Have fun
Hey jfrail,
This is pretty simple actually, all you have to do is place this code within the for loop of your variants.
{% assign sortedVariants = product.variants %} {% for variant in sortedVariants %} {% if variant.available %} {% capture discount %} {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%) {% endcapture %} You save: {{ discount }} {% endif %} {% endfor %}
Hello Starbadar,
Thank you so much for the fast respond. I tried what you suggest and it doesn't work for me. I am using debut theme, for some reason can you tell where should I put it?
I really appreciate it. Thank you.
Well, that depends on which version of Debut you have, I'm not familiar with all versions however assuming you want this data to show next to the pricing you should see something like this in product-template.liquid.
<div class="product__price"> {% include 'product-price', variant: current_variant %} </div>
If that's the case then you wanna go into product-price.liquid
On line 45 Change
<div class="price__sale"> <dt> <span class="visually-hidden visually-hidden--inline">{{ 'products.product.sale_price' | t }}</span> </dt> <dd> <span class="price-item price-item--sale" data-sale-price> {{ money_price }} </span> <span class="price-item__label" aria-hidden="true">{{ 'products.product.on_sale' | t }}</span> </dd> </div>
To this
<div class="price__sale"> <dt> <span class="visually-hidden visually-hidden--inline">{{ 'products.product.sale_price' | t }}</span> </dt> <dd> <span class="price-item price-item--sale" data-sale-price> {{ money_price }} </span> <span class="price-item__label" aria-hidden="true">{{ 'products.product.on_sale' | t }}</span>
<span class="price-item price-item--sale">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span> </dd> </div>
Tadaaa
Starbadar,
I have tried what you instruct and follow it carefully. I believe we have the same debut version because all the codes that you show are very similar to mine.
The problem is when I selected a new variant the percentage discount disappear.
Thank you for your response.
Okay. Thanks a lot. I'll be gladly waiting.
This is an accepted solution.
ok I'm back now, sorry bout the wait, aight so the issue is that your data-sale-price is controlled by a function within theme.js which changes the value based on the variant selected, Shopify's liquid isn't as good as Angular or React yet, basically, you can't double bind elements in order to refresh the data once it's loaded which is why liquid.... is far behind and sucks but that's life, so Javascript to the rescue.
On line 51, you'll find this
<span class="price-item price-item--sale" data-sale-price>
Doing a quick search through theme.js we can trace where the data is being changed and there we go, let's change the code a bit to have it render what we want. However before let's change the liquid a bit to this
<div class="price__sale"> <dd> <div class="price-item price-item--sale" data-sale-price> {{ money_price }} <div class="price-item price-item--sale--save">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span> </div> </dd> </div>
Basically, I remove the Sale string as it's no longer needed and moved the sale up.
In Theme.js
On line 3678 You should see this:
$salePrice.html( theme.Currency.formatMoney(variant.price, theme.moneyFormat) );
Change it to this
$salePrice.html( '<div class="price-item price-item--sale">' + theme.Currency.formatMoney(variant.price, theme.moneyFormat) + '<div class="price-item price-item--sale--save">You save: ' + theme.Currency.formatMoney(variant.compare_at_price - variant.price, theme.moneyFormat) + ' (' + Math.round((1 - (variant.price / variant.compare_at_price)) * 100) + '%) ' + '</div>' + '</div>' );
It could be refactored a bit with more elegant code but ES6 isn't compatible with most older browsers which represent 5-15% of your sales, unless you installed a polyfill library like babel.js
Voila, it works now.
Have fun
Hi Starbadar,
Thank you so much for your help. This saves me from my work.
This is absolutely great and works like charm.
I now understand that liquid cannot alter an html element without reloading the page. Anyway, Thanks a lot.
Have a great day ahead.
It just prints out all possible price options. The calculations are correct.
But the discount for the currently chosen variant should be displayed. How to fix it?
I use the Dawn theme.
Hi, did you resolve the issue? I'm facing the same problem
Hey Community! As we jump into 2025, we want to give a big shout-out to all of you wh...
By JasonH Jan 7, 2025Hey Community! As the holiday season unfolds, we want to extend heartfelt thanks to a...
By JasonH Dec 6, 2024Dropshipping, a high-growth, $226 billion-dollar industry, remains a highly dynamic bus...
By JasonH Nov 27, 2024