Product Price % OFF not changing with selected variant - shopify

Please help me to resolve this code. I have some % off discount to show based on the variant choose, its not getting changed on clicking on pack of 2 and pack of 3, as we have different % in discounts. This is my shopify product url https://us.buywow.com/products/wow-apple-cider-shampoo-cocounut-oil-conditioner-set-500ml
Callback function is written, but I am not understanding why its not changing
Product.liquid
<!-- /templates/product.liquid -->
{% assign on_sale = false %}
{% if product.compare_at_price > product.price %}
{% assign on_sale = true %}
{% endif %}
.
.
.
.
{% comment %}
------ Product Price ------
{% endcomment %}
<div class="product_prices">
<span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span>
<h4 id="ProductPrice" class="product-regular-price" itemprop="price" content="{{ current_variant.price | divided_by: 100.00 }}">
{{ current_variant.price | money }}
</h4>
<span class="old-price">{{ current_variant.compare_at_price | money }}</span>
{% if on_sale %}
<div class="save_money_block">
<span class="save_off">
{% if current_variant.compare_at_price > current_variant.price %}
{{ current_variant.compare_at_price | minus: current_variant.price | times: 100.0 |
divided_by: current_variant.compare_at_price | money_without_currency | times: 100
| replace: '.0', ''}}% OFF{% endif %}
</span>
</div>
{% endif %}
</div>
.
.
.
.
.
<script>
(function(s3d) {
if (!s3d) {
console.warn('"window.Shopify3d" does not exist. Please ensure you\'ve added the <script> to your theme');
return;
}
{% for variant in product.variants %}
s3d.mapMetafieldAssets('{{ variant.id }}', '{{ variant.metafields.shopify3d['assets'] }}');
{% endfor %}
})(window.Shopify3d);
</script>
<script>
var selectCallback = function(variant, selector) {
timber.productPage({
money_format: "{{ shop.money_format }}",
variant: variant,
selector: selector
});
};
</script>
On selecting Pack Of 3 - 60% OFF should be the resultant.
that is not happening auto refresh.

Remember that Liquid is compiled server-side before the document is sent to the client's browser, so the result is not dynamic and will not be able to automatically update when a variant is selected.
In order to make the percent-off part change appropriately when the selections change, you will need to add javascript code that will run whenever the variant selection changes. Fortunately, you already have a function that will do that, in your theme it happens to be called selectCallback, which then calls a function called timber.productPage to do all the heavy lifting.
You will want to update either selectCallback or timber.productPage with the javascript code needed to update your percent-off field. (The latter is probably the better option in your case, as that would keep all of the relevant price-display-updating code close together.) The variant parameter will either be the currently-selected variant or undefined if the current option selections do not match any of the variants in the product; the selector parameter will contain a lot of generally-useful information, such as the parent product object.
Hope this helps!

In the selectCallback function add next code:
<script>
var selectCallback = function(variant, selector) {
var $discount = $('#offpercent'),
$productPrice = $('#productPrice'),
$comparePrice = $('#comparePrice');
alert(Shopify.formatMoney(variant.price, Shopify.money_format));
alert(Shopify.formatMoney(variant.compare_at_price, Shopify.money_format));
var percDiff = Math.round((variant.compare_at_price-variant.price)/variant.compare_at_price * 100);
alert(percDiff);
$discount.html(percDiff);
};
</script>

Related

'size' on custom product metafield returns '0'

I'm building a component which checks the character count of a custom product metafield; if it's above 24 characters, the data is output as an accordion, otherwise the metafield content is printed in its entirety. The conditional below fails as the metafield size always returns 0, but I can see the content printing via the else statement so I'm certain the path is valid:
{% if product.metafields.custom.product_note.size >= 24 %}
<div class="product-note has--dropdown">
<span class="item__heading item__trigger">Product information</span>
<div class="item__content">
{{ product.metafields.custom.product_note }}
</div>
</div>
{% else %}
<div class="product-note">
<div class="item__content">
{{ product.metafields.custom.product_note }}
</div>
</div>
{% endif %}
I'm not sure it's relevant, but the product_note metafield is a multi-line text field. If anyone could point me in the right direction as to why size is failing to produce a value, I'd appreciate it massively.
You could always try working off the value contained in the metafield. It appears you are short-cutting by referring to just the combo of namespace and key, without actually saying: what is the length of the value stored at that namespace and key. Just a thought. You could at least try that.
Final answer, courtesy of #David Lazar's suggestion:
{% assign data_product_note = product.metafields.custom.product_note.value %}
{% if data_product_note.size >= 24 %}
<div class="product-note has--dropdown">
<span class="item__heading item__trigger">Product information</span>
<div class="item__content">
{{ data_product_note }}
</div>
</div>
{% else %}
<div class="product-note">
<div class="item__content">
{{ data_product_note }}
</div>
</div>
{% endif %}

Shopify Liquid - Get the URL for a variant's image

On a Shopify product page, I can loop through all the variants and get information about them like this:
{% for variants in product.variants %}
{{ variants.id }}<br>
{{ variants.sku }}<br>
{{ variants.title}}<br>
{{ variants.price | divided_by: 100}}<br>
{% endfor %}
This works perfectly fine, however when I try and get the variant image in the loop like this:
{{ variants.image}}
I have also tried using:
{{ variants.featured_image.src}}
Which produces exactly the same result.
The output is simpy products and then the name of the image file. For example 'products/my-image.jpg'.
This is obviously not the path to the image and when I try and display this within an image tag, a broken image is produced.
I am trying to get the path to the image that is stored on Shopify's CDN for this variant product, which will look something like https://cdn.shopify.com/s/files/1/0022/4572/2212/products/WI1M1L1F1B1_grande.jpg?v=1656698226.
Does anyone know how this can be achieved within the loop I am using above?
You are looking for this
{{ variant.image.src | product_img_url: '200x' }}
I suggest you to take a look here to find many other useful functions: https://www.shopify.ca/partners/shopify-cheat-sheet
Also is useful to download a free theme (Dawn for example) and use it as reference.
Here is a code example to show each variant image and url :
<div class="product_thumbnails">
{% for variant in product.variants %}
<a href="{{ variant.url }}">
<div class="h-[50px] w-[50px] bg-[#E6ECEB] rounded shrink-0 p-1">
{{ variant.image | image_url: width: 50 | image_tag }}
</div>
</a>
{% endfor %}
</div>

Shopify: Display discount codes in new order email template

I want to display discount codes in new order email notification template, using this code:
{% for discount in discounts %}
{{ discount.code }} : {{ discount.savings | money_with_currency }}
{% endfor %}
It's displaying the discount amount but not the discount code name/title. It's returning blank even if the discount is manually entered in the back-end when creating an order.
How can I display discount codes no matter where it's entered i.e in admin or checkout?
In notifications you may access to discount_application object as explained here:
https://shopify.dev/docs/themes/liquid/reference/objects/discount-application
So (not tested), something like that might work:
{% for discount_application in discount_applications %}
{{ discount_application.title }} : {{ discount_application.value }}
{% endfor %}
HTH
You can get it from your cookies:
<div id="discount-message"></div>
<script type="text/javascript">
var codeCookieValue;
var getCookie = function(name) {
var value = "; " + document.cookie;
var parts = value.split('; '+name+'=');
if (parts.length == 2) return parts.pop().split(";").shift();
};
codeCookieValue = getCookie('discount_code');
</script>

Shopify variant swatches or radio buttons instead of dropdowns in Slate

Shopify's tutorial for color swatches isn't supported yet for Slate,
and the select callback referenced no longer exists in the code base. Is it possible to modify this tutorial to work on Slate themes to create radio buttons or swatches instead of a dropdown for selecting variants on the product template?
Yes. I was able to get this tutorial to work by modifying the code slightly. This workaround is only going to be relevant until the shopify tutorial is updated to correspond to Slate.
Follow the tutorial as per the directions.
When you get to the step "Locate your selectCallback function",
you will notice there is no selectCallback function in Slate. Yikes!
Instead find "_onSelectChange" in theme.js and add the code there.
This is the final function with the swatches code added:
/**
* Event handler for when a variant input changes.
*/
_onSelectChange: function() {
var variant = this._getVariantFromOptions();
this.$container.trigger({
type: 'variantChange',
variant: variant
});
if (!variant) {
return;
}
// BEGIN SWATCHES
var selector = this.originalSelectorId;
if (variant) {
var form = $(selector).closest('form');
for (var i=0,length=variant.options.length; i<length; i++) {
var radioButton = form.find('.swatch[data-option-index="' + i + '"] :radio[value="' + variant.options[i] +'"]');
if (radioButton.size()) {
radioButton.get(0).checked = true;
}
}
}
// END SWATCHES
this._updateMasterSelect(variant);
this._updateImages(variant);
this._updatePrice(variant);
this.currentVariant = variant;
if (this.enableHistoryState) {
this._updateHistoryState(variant);
}
},
Then, once you've completed the tutorial, you will notice it's still not working. This is because the code you add to theme.liquid uses a class that is no longer on your variant Selects.
On product.liquid (this is a Section on most Slate themes) Add the class "single-option-selector" to your selects, like so:
{% unless product.has_only_default_variant %}
{% for option in product.options_with_values %}
<div class="selector-wrapper js">
<label for="SingleOptionSelector-{{ forloop.index0 }}">
{{ option.name }}
</label>
<select
id="SingleOptionSelector-{{ forloop.index0 }}"
class="single-option-selector"
data-single-option-selector
data-index="option{{ option.position }}">
{% for value in option.values %}
<option value="{{ value | escape }}"
{% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{% endfor %}
</select>
</div>
{% endfor %}
{% endunless %}
Now, the tutorial should work as it's supposed to. I hope this helps someone out!

Shopify , show product options as 3 seperate dropdowns instead of 1 single dropdown

On my product page, with the following line of code in the product.liquid template, it generates 3 seperate dropdowns for the 3 different product options the product has, eg Type Color Size..
<div class="select">
<select id="product-select" name="id">
{% for variant in product.variants %}
<option {% if variant == product.selected_or_first_available_variant %}selected="selected"{% endif %} value="{{ variant.id }}">{{ variant.title }}</option>
{% endfor %}
</select>
</div>
however, i used the same code in the product-loop.liquid to show the same drop down on the collections page (without the option to add to cart).. but this time the dropdown appears as 1 single combined dropdown.
how do i split them up like before?
heres a screenshot of what both dropdowns look like :
You need to include option_selection.js in your collection.liquid template.
paste the following line at top or bottom of your collection.liquid template
{{ 'option_selection.js' | shopify_asset_url | script_tag }}