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

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 }}

Related

How to add product metafeilds on any page in shopify

I am attempting to add a product meta fields in a quick view product option on my product collection,
Here is the code I am using, the meta field in the tag is not working
{%- if collection.title == "vluevlockers" -%}
<div class="sizing-text">
<h2 class="help-text">sizing information of the frames</h2>
<p>{{ product.metafields.custom.frames_set_blueblocker }}</p>
<div class="bold_options"> </div>
</div>
{%- endif -%}
When I try to console.log the meta field it gives me null, But the same meta field is working fine on the single product page.

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>

Capture two variables in liquid

What I want to do:
Capture two variables {{section.settings.{{title}}_modal_title}}
Context:
The links in the linklist are not really used as links, but purely so user can reorganize it in their Shopify portal.
External javascript file creates elements (modals) on click event, value from section.settings.XXX_modal_title is supposed to be used in the created modals.
The linklist:
<ul class="menu">
{% for link in linklists.main-menu.links %}
<li data-menu="{{ link.title | upcase }}" class="menu-link">
<p class="menu-title">[{{ link.title | upcase }}]</p> <-- Click event
</li>
{% endfor %}
</ul>
What I tried:
My first try was adding the liquid tag itself with .insertAdjacentHTML('afterbegin', {{section.settings.${attLowerCase}_modal_title}}) when the element is created, but soon realized that liquid renders the values first. The output of doing this is literally "{{ }}"
My second try was to capture two variables and put it in a hidden input.
{% assign title = link.title | downcase %}
{% capture section_title_variable %}
{{section.settings.{{title}}_modal_settings}}
{% endcapture %}
<hr class="item-line">
<p class="ueq-menu-title">[{{ link.title | upcase }}]</p>
<input type="hidden" id="about_modal_title" value="{{section_title_variable}}">
In depth example:
section.settings
{
"type": "text",
"id": "about_modal_title",
"label": "About window title",
"default": "ABOUT"
},
User clicks on link ABOUT
<ul class="menu">
{% for link in linklists.ueq-menu.links %}
<li data-menu="{{ link.title | upcase }}" class="menu-link"> <-- "ABOUT"
{% assign title = link.title | downcase %} <-- downcase to "about"
{% capture section_title_variable %}
{{section.settings.{{title}}_modal_title}}
{% endcapture %}
<hr class="item-line">
<p class="menu-title">[{{ link.title | upcase }}]</p>
<input type="hidden" id="about_modal_title" value="{{section_title_variable}}"> <-- captured should look like this {{section.settings.about_modal_title}}
</li>
{% endfor %}
</ul>
on click event, get the value from hidden input, and use it when creating elements.
"Why not use {% javascript %}?"
I prefer to do it this way, since most of my script files are external. I like to keep it that way.
"Why capture it like that?"
The links in the linklist are already known, this was in the design. Thats why in sechema one of them is called "about_modal_title". Since this is used inside a for loop, this was the only way I could come up with to connect the title and schema settings with each other.
If someone knows a better way to do this instead of putting it in a hidden input, please let me know :)
In proper Liquid syntax, curly-brackets are never embedded inside curly-brackets
The syntax {{ something_{{ you }}_want }} is illegal Liquid syntax - once an expression is started, using either {{ or {%, everything up to the next }} or %} is evaluated as one template command.
In your example, you're looking to combine two strings in order to get the name of a setting that you want to access. In a dedicated programming language, we would expect there to be nice shortcuts for something like this. Liquid, however, is first and foremost a templating language, and doesn't have such shortcuts. Instead, we will need to accomplish our goal in two steps.
The first thing we need to know is that we can access properties in two ways: {{ settings.fieldname }} is equivalent to {{ settings['fieldname'] }}
Thanks to that second syntax, we can access an arbitrary setting using a variable:
{% assign field = 'fieldname' %}
{{ settings[fieldname] }}
So to do something more complicated, we just need to use assign (or capture - just be aware that capture includes whitespace as well!) to get a variable that contains the name of the field we want to access, then pass that in to the square brackets:
{% assign title_field = link.title | downcase | append: '_modal_title' %}
{{ section.settings[title_field] }}

Product Price % OFF not changing with selected variant

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>

Shopify Listing Variants in other product page

I have an online store on Shopify. What I am trying to do is on a product page, have a "also needed" type list. I've created all my lists and other items, but what I can't seem to figure out is how to list the variants of one product on another product page.
What I have for my option menu is this:
<select id="product-select" name="id" data-id="{{ 304164943 }}">
{% for variants in product.variants %}
<option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
{% endfor %}
</select>
which outputs:
<select id="product-select" name="id" data-id="304164943">
<option value=""> - </option>
<option value=""> - </option>
<option value=""> - </option>
<option value=""> - </option>
<option value=""> - </option>
<option value=""> - </option>
the data-id of 304164943 is for the product I want to list the variants of but the dropdown menu this generates is empty.
You can not access a product via its ID with Liquid. You can however access it will the handle. So if the handle was known you could do this:
{% assign relatedProduct = all_products['some-handle'] %}
{% for relatedVariant in relatedProduct.variants %}
<option value="{{ relatedVariant.id }}">{{ relatedVariant.title }} - {{ relatedVariant.price | money }}</option>
{% endfor %}
You've also got an error in your loop code posted - it should be for variant, not for variants. I'm guessing that's just a typo here.
The product page will only return the object of the product belonging to that page. It won't return the object of another product. So to access this you'd need to do some javascript jiggery pokery or create a link list. Here is a tutorial using a link list:
http://www.tetchi.ca/shopify-tutorial-how-to-create-a-part-picker-form/
Or, you can go the JS route. You'd need to grab the product object via ajax, and append the returned data to the page. To grab this data, you'd need to do an ajax get using the Ajax api:
https://docs.shopify.com/support/your-website/themes/can-i-use-ajax-api
So if using jquery - something like this would work: (where <product-handl> is the handle of the product you wish to insert)
$.get( "/products/<product-handle>.js", function( data ) {
var variants = data.variants; // all your variants
// Then you can loop over the variants insert the options into your page...
});
As this is added after the page has rendered, you'll need to do some ajaxy cart stuff so you can put stuff in the cart. Your theme may already have some ajaxy cart stuff in it.