How to call option.value in the loop of product.variants in Shopify? - shopify

I have one hidden dropdown and two variant-selector dropdowns. One dropdown is for color and the second one is for size. I want to add size data in data-size="" and color data in data-color="" in the dropdown of name=id.
<form method="post" action="/cart/add">
{% if product.variants.size > 1 %}
{% for option in product.options_with_values %}
<select class="variant-selector {{option.name}}" data-var="{{forloop.index}}">
{% if product.available %}
{% for values in option.values %}
<option value="{{values}}">{{values}}</option>
{% endfor %}
{% endif %}
</select>
{% endfor %}
<select name="id" style="display:none;" id="data{{forloop.index}}">
{% for variant in product.variants %}
{% if variant.available %}
<option data-size="" data-color="" value="{{ variant.id }}" >{{ variant.title }}</option>
{% endif %}
{% endfor %}
</select>
{% if variant.available%}
<input type="hidden" min="1" type="number" name="quantity" value="1" />
<input type="submit" value="{{ 'products.product.add_to_cart' | t }}" class="btn add-to-cart" />
{% else %}
<input type="submit" value="{{ 'products.product.sold_out' | t }}" class="btn add-to-cart" disabled="disabled">
{% endif %}
{% endif %}
</form>

As Dave B comment I don't need option.value in the loop of product.variants in Shopify. I simply add data-size="{{ variant.option1 }}" and data-color="{{ variant.option2 }}"
<select name="id" style="display:none;" id="data{{forloop.index}}">
{% for variant in product.variants %}
{% if variant.available %}
<option data-size="{{ variant.option1 }}" data-color="{{ variant.option2 }}" value="{{ variant.id }}" >{{ variant.title }}</option>
{% endif %}
{% endfor %}
</select>

Related

I need to display a variant image on a radio button variant selector, but can't seem to find how to properly pull the variant img src. Shopify

So I'm on Shopify product template (using Debut Theme). I changed the default dropdown variant selector to radio buttons and it works great. I wanted the radio buttons to display the variant image, and that's where I'm stuck. (Here's a link to a test product where I want this to work: TEST product link
Here's the radio button form:
{% form 'product', product, class:form_classes %}
{% unless product.has_only_default_variant %}
{% for option in product.options_with_values %}
<label style="font-weight: 700; font-size: 1.2em;"{% if option.name == 'default' %}class="label--hidden" {% endif %}for="SingleOptionSelector-{{ forloop.index0 }}">
¡Escoge la versión que quieres!
</label>
{% assign option_position = forloop.index %}
<fieldset class="botones-radio">
{%- for value in option.values -%}
<div class="imagen-mas-boton">
<input type="radio" class="single-option-selector-{{ section.id }} "
{% if option.selected_value == value %} checked="checked"{% endif %}
value="{{ value | escape }}"
data-index="option{{option_position}}"
name="{{ option.name | handleize }}"
id="SingleOptionSelector-{{option_position}}">
<img src="{{ featured_image | img_url: '200x' }}" />
<label style="text-align: center;" for="SingleOptionSelector-{{ forloop.index0 }}">
{{value}}
</label>
</div>
{%- endfor -%}
</fieldset>
{% endfor %}
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
{% if variant.available %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">
{{ variant.title }}
</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - {{ 'products.product.sold_out' | t }}</option>
{% endif %}
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
<div class="product-form__item product-form__item--quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1" class="product-form__input" pattern="[0-9]*">
</div>
{% endif %}
<div class="product-form__item product-form__item--submit{% if section.settings.enable_payment_button %} product-form__item--payment-button{% endif %}{% if product.has_only_default_variant %} product-form__item--no-variants{% endif %}">
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
<button type="submit" name="add" id="AddToCart-{{ section.id }}" {% unless current_variant.available %}disabled="disabled"{% endunless %} class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}">
<span id="AddToCartText-{{ section.id }}">
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
</button>
</div>
{% endform %}
Now, the <img src="{{ featured_image | img_url: '200x' }}" /> obviously displays the featured image so both variants will display the same image, and both will change when selecting the other variant and refreshing the page.
I want to display the image assigned to each variant. I tried <img src="{{ variant| img_url: '200x' }}" /> and <img src="{{ variant.image | img_url: '200x' }}" />
But it doesn't seem to work.
I also would like to display each variants price on the lable, for this I tried the following:
<label style="text-align: center;" for="SingleOptionSelector-{{ forloop.index0 }}"> {{value}} {{current_variant.price | money }} </label>
but this will show the price of the selected variant and will only change when refreshed.

Shopify Liquid attributes inside select tag

I want to ask that what are the following 2 attributes in side select tag. I searched them in theme.js file but they are not present there ?
data-product-select
data-free-shipping=true
<select name="id" class="no-js" data-product-select data-free-shipping=true >
{% for variant in product.variants %}
<option
{% if variant == current_variant %}selected="selected"{% endif %}
{% unless variant.available %}disabled="disabled"{% endunless %}
value="{{ variant.id }}" data-variant-name="{{ variant.title }}" data-variant-image="{{ variant.image.src | img_url }}"
data-sale={% if variant.compare_at_price > variant.price %}true {% else %}false{% endif %}
{% if thirty_days_after_publication > todays_date %}data-new-product=true{% endif %}>
{{ variant.title }}
</option>
{% endfor %}
</select>

Shopify - Change size variant from select dropdown to buttons

I would like to change my variant display from dropdown (select) to using buttons instead. I cannot find any up to date guides elsewhere online. I am using the Debut shopify theme.
it currently looks like this dropdown but I want to change this to buttons with the sizes. i.e. so you click your desired size button and then click the standard 'add to cart' button (which is already in place, but currently for the dropdown) below it.
Here is the code:
{% capture "form_classes" -%}
product-form product-form-{{ section.id }}
{%- unless section.settings.show_variant_labels %} product-form--hide-variant-labels {% endunless %}
{%- if section.settings.enable_payment_button and product.has_only_default_variant %} product-form--payment-button-no-variants {%- endif -%}
{%- if current_variant.available == false %} product-form--variant-sold-out {%- endif -%}
{%- endcapture %}
{% form 'product', product, class:form_classes, novalidate: 'novalidate', data-product-form: '' %}
{% unless product.has_only_default_variant %}
<div class="product-form__controls-group">
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<label {% if option.name == 'default' %}class="label--hidden" {% endif %}for="SingleOptionSelector-{{ forloop.index0 }}">
{{ option.name }}
</label>
<select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
id="SingleOptionSelector-{{ forloop.index0 }}"
data-index="option{{ forloop.index }}"
>
{% for value in option.values %}
<option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{%- if variant == current_variant %} selected="selected" {%- endif -%}
>
{{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
<div class="product-form__controls-group">
<div class="product-form__item">
<label for="Quantity-{{ section.id }}">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity-{{ section.id }}"
name="quantity" value="1" min="1" pattern="[0-9]*"
class="product-form__input product-form__input--quantity" data-quantity-input>
</div>
</div>
{% endif %}
<div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
data-error-message-wrapper
role="alert"
>
<span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
{% include 'icon-error' %}
<span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
</div>
<div class="product-form__controls-group product-form__controls-group--submit">
<div class="product-form__item product-form__item--submit
{%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
{%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
>
<button type="submit" name="add"
{% unless current_variant.available %} aria-disabled="true"{% endunless %}
aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
class="btn btn--rounded product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
data-add-to-cart>
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
<span class="hide" data-loader>
{% include 'icon-spinner' %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
</div>
{% endform %}
</div>
Thanks a lot!
Replace your select boxes with input radio buttons:
{%- for variant in product.variants -%}
<input
type="radio"
name="id"
class="variant-option"
value="{{ variant.id }}"
id="variant-option-{{ variant.id }}"
{% unless variant.available %} disabled{% endunless %}
{% if product.selected_variant.id == variant.id %} checked{% endif %}
>
<label for="variant-option-{{ variant.id }}">{{ variant.title }}</label>
{%- endfor -%}
And then just add some styles to display these inputs as buttons e.g:
.variant-option + label {
background-color: #f2f2f2;
padding: 10px 15px;
margin: 0 5px;
}
.variant-option:checked + label {
background-color: #000;
color: #fff;
}
.variant-option[disabled] + label {
opacity: 0.5;
}
.variant-option {
display: none;
}

Multi file uploader in Shopify Debut theme

I'm customizing my page to upload multiple files (photos). This is the code that I have so far and according to this link it should work:
https://shopify.dev/tutorials/customize-theme-get-customization-information-for-products
in the link go to "Allow file uploads" if you want to check.
{% form 'product', product, class:form_classes, data-product-form: '', enctype:"multipart/form-data" %}
{% unless product.has_only_default_variant %}
<div class="product-form__controls-group">
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
id="SingleOptionSelector-{{ forloop.index0 }}"
data-index="option{{ forloop.index }}"
>
{% for value in option.values %}
<option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{%- if variant == current_variant %} selected="selected" {%- endif -%}
>
{{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
{% comment %}
<div class="product-form__controls-group">
<div class="product-form__item">
<input type="number" id="Quantity-{{ section.id }}"
name="quantity" value="1" min="1" pattern="[0-9]*"
class="product-form__input product-form__input--quantity" data-quantity-input
>
</div>
</div>
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
{% endcomment %}
{% endif %}
<div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
data-error-message-wrapper
role="alert"
>
<span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
{% include 'icon-error' %}
<span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
</div>
<div class="product-form__controls-group product-form__controls-group--submit">
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
<div class="product-form__item product-form__item--submit
{%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
{%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
>
<button type="submit" name="add"
{% unless current_variant.available %} aria-disabled="true"{% endunless %}
aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
data-add-to-cart>
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
<span class="hide" data-loader>
{% include 'icon-spinner' %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
</div>
</div>
{% endform %}
This is my form that according to the link must have the attribute
enctype = "multipart / form-data".
At the bottom of the form it is in input type = "file".
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
And this is the code in the cart-template.liquid.
<div class="list-view-item__title">
<a href="{{ item.url }}" class="cart__product-title" data-cart-item-title>
{{ item.product.title }}<br>
{% assign property_size = item.properties | size %}
{% if property_size > 0 %}
{% for p in item.properties %}
{{ item.properties.count }}
{% assign first_character_in_key = p.first | truncate: 1, '' %}
{% unless p.last == blank or first_character_in_key == '_' %}
{{ p.first }}:
{% if p.last contains '/uploads/' %}
<a class="lightbox" href="{{ p.last }}">{{ property_size }}</a>
{% else %}
{{ p.last }}
{% endif %}
<br>
{% endunless %}
{% endfor %}
{% endif %}
</a>
</div>
The problem is the property_size variable gets value one even if I upload two or more images, when in fact I should return the amount of properties that the item has.
Can anyone help me please? What I am doing wrong?
The Debut theme probably has changed since this tutorial was uploaded, and since it is not supported, probably won't be updated.
If you add a type="text" input instead of a type="file" the property gets added as expected. This happens because the _initAddToCart function (assets/theme.js line 6447) gets the form HTML element and pass it along to another function.
var $data = $(this.selectors.productForm, this.$container);
this._addItemToCart($data);
Then in the _addItemToCart function (assets/theme.js line 6513), the form is serialized to a string:
var params = {
url: '/cart/add.js',
data: $(data).serialize(),
dataType: 'json',
};
$.post(params).done(...
This function will ignore the file inputs, as explained in the jQuery documentation:
Data from file select elements is not serialized.
To send the file, the FormData browser API can be used. But to use it with the jQuery AJAX call, some properties must be set:
var params = {
url: '/cart/add.js',
// data: $(data).serialize(),
dataType: 'json',
// Disable the jQuery data processing, and send the FormData object
contentType: false,
processData: false,
data: new FormData($(data).get()[0])
};
$.post(params).done(...
However, since the HTML file <input> has name="properties[Photo]", only the last of the uploaded files will be added to the cart item's Photo property.
I tried with name="properties[Photo][]", but the cart/add.js call only returns an error 500 with the message "Internal Server Error".
So to upload multiple files you could add some custom code to the _addItemToCart function, to get each File from the <input> and add to the FormData with a different key for each file.

Shopify - Hiding sold out variants on dropdown (regular solution not working)

On my Shopify store I need to be able to hide sizes in the dropdown that are no longer available. I have tried multiple times adding the code that Shopify suggests here but I am using the Retina Out of the Sandbox theme and add that code to the product-form.liquid file and what happens is only 1 size becomes available no matter what. My store is in dire need of this feature because we sell tons of closeout shoes no longer available so when a customer searches for a size products that have a sold out size 9 still show because it is not hidden on the dropdown, it just says Sold Out, here is my code. Apologies if the formatting is not so nice looking, this is what came with my theme.
product-form.liquid
{% if product.available %}
<form action="/cart/add" method="post" class="clearfix product_form" data-money-format="{{ shop.money_format }}" data-shop-currency="{{ shop.currency }}" id="product-form-{{ product.id }}">
{% if settings.display_inventory_left %}
<div class="items_left">
{% if product.variants.first.inventory_management == "shopify" and product.variants.first.inventory_quantity > 0 %}
<p><em>{{ product.variants.first.inventory_quantity }} {{ settings.inventory_left_text | escape }}</em></p>
{% endif %}
</div>
{% endif %}
{% if product.options.size > 1 %}
<div class="select">
<select id="product-select-{{ product.id }}" 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>
{% elsif product.options.size == 1 and (product.variants.size > 1 or product.options[0] != "Title") %}
<div class="select">
<label>{{ product.options[0] }}:</label>
<select id="product-select-{{ product.id }}" 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>
{% else %}
<input type="hidden" name="id" value="{{ product.variants.first.id }}" />
{% endif %}
{% if settings.display_product_quantity %}
<div class="left">
<label for="quantity">Quantity:</label>
<input type="number" min="1" size="2" class="quantity" name="quantity" id="quantity" value="1" />
</div>
{% endif %}
<div class="purchase clearfix {% if settings.display_product_quantity %}inline_purchase{% endif %}">
{% if settings.cart_return == 'back' %}
<input type="hidden" name="return_to" value="back" />
{% endif %}
<input type="submit" name="add" value="{{ settings.add_to_cart_text | escape }}" class="action_button add_to_cart" />
</div>
</form>
{% if product.variants.size > 1 or product.options.size > 1 %}
<script type="text/javascript">
// <![CDATA[
$(function() {
$product = $('#product-' + {{ product.id }});
new Shopify.OptionSelectors
("product-select-{{ product.id }}",{
product: {{ product | json }},
onVariantSelected: selectCallback{% if product-form == 'product' %},
enableHistoryState: true{% endif %}
});
{% if product.options.size == 0 %}
{% for variant in product.variants %}
{% unless variant.available %}
jQuery('.single-option-selector option').filter(function() { return jQuery(this).html() === {{ variant.title | json }}; }).remove();
{% endunless %}
{% endfor %}
jQuery('.single-option-selector').trigger('change');
{% endif %}
// ]]>
</script>
{% endif %}
{% endif %}
A couple of small things I noticed:
{% if product.options.size == 0 %} should be {% if product.options.size == 1 %} (see here).
You're missing the closing brackets for $(function() {.... You need }); before the closing </script> tag.
This seems to work for me now:
{% if product.variants.size > 1 or product.options.size > 1 %}
<script type="text/javascript">
// <![CDATA[
$(function() {
$product = $('#product-' + {{ product.id }});
new Shopify.OptionSelectors
("product-select-{{ product.id }}",{
product: {{ product | json }},
onVariantSelected: selectCallback{% if product-form == 'product' %},
enableHistoryState: true{% endif %}
});
{% if product.options.size == 1 %} // *** should be 1, not 0 ***
{% for variant in product.variants %}
{% unless variant.available %}
jQuery('.single-option-selector option').filter(function() { return jQuery(this).html() === {{ variant.title | json }}; }).remove();
{% endunless %}
{% endfor %}
jQuery('.single-option-selector').trigger('change');
{% endif %}
}); // *** missing closing brackets here ***
// ]]>
</script>
{% endif %}