Shopify themes, liquid, logos, and UX
Hi,
I am trying to edit the Dawn theme such that the product listing has the first option selector as a pill and the second option selector as dropdown as I have many variants under the second option and the pill layout doesn't look good with so many pills.
I have edited the main-product.liquid variant picker code as follows and while it looks right when rendered, as soon as I choose any option on the product page it says that the product is unavailable which is not correct. I think it is trying to verify the selection against the variants in the json file and failing, but this is a hunch. Can anyone help.
{%- when 'variant_picker' -%} {%- unless product.has_only_default_variant -%} <variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}> {%- for option in product.options_with_values -%} {% if forloop.first %} <fieldset class="js product-form__input"> <legend class="form__label">{{ option.name }}</legend> {%- for value in option.values -%} <input type="radio" id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" name="{{ option.name }}" value="{{ value | escape }}" form="{{ product_form_id }}" {% if option.selected_value == value %}checked{% endif %} {%- for variant in product.variants -%} {% if value == variant.title %} {% if variant.available == false %}class="outofstock" {% endif %} {% endif %} {%- endfor -%} > <label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" {%- for variant in product.variants -%} {% if value == variant.title %} {% if variant.available == false %}class="outofstock" {% endif %} {% endif %} {%- endfor -%} > {{ value }} </label> {%- endfor -%} </fieldset> {%- else -%} <div class="product-form__input product-form__input--dropdown"> <label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}"> {{ option.name }} </label> <div class="select"> <select id="Option-{{ section.id }}-{{ forloop.index0 }}" class="select__select" name="options[{{ option.name | escape }}]" form="{{ product_form_id }}" > {%- for value in option.values -%} <option value="{{ value | escape }}" {% if option.selected_value == value %}selected="selected"{% endif %}> {{ value }} </option> {%- endfor -%} </select> {% render 'icon-caret' %} </div> </div> {%- endif -%} {%- endfor -%} <script type="application/json"> {{ product.variants | json }} </script> </variant-radios> {%- endunless -%} <noscript class="product-form__noscript-wrapper-{{ section.id }}"> <div class="product-form__input{% if product.has_only_default_variant %} hidden{% endif %}"> <label class="form__label" for="Variants-{{ section.id }}">{{ 'products.product.product_variants' | t }}</label> <div class="select"> <select name="id" id="Variants-{{ section.id }}" class="select__select" form="{{ product_form_id }}"> {%- for variant in product.variants -%} <option {% if variant == product.selected_or_first_available_variant %}selected="selected"{% endif %} {% if variant.available == false %}disabled{% endif %} value="{{ variant.id }}" > {{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %} - {{ variant.price | money | strip_html }} </option> {%- endfor -%} </select> {% render 'icon-caret' %} </div> </div> </noscript>
Thanks,
Online_Seller
Solved! Go to the solution
This is an accepted solution.
Hi @Online_Seller,
Please change all code:
{%- when 'variant_picker' -%}
{%- unless product.has_only_default_variant -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}
<fieldset class="js product-form__input {% unless forloop.first %}hidden{% endunless %}">
<legend class="form__label">{{ option.name }}</legend>
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="{{ product_form_id }}"
{% if option.selected_value == value %}checked{% endif %}
>
<label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}">
{{ value }}
</label>
{%- endfor -%}
</fieldset>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-radios>
<variant-selects class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}
<div class="product-form__input product-form__input--dropdown {% if forloop.first %}hidden{% endif %}">
<label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}">
{{ option.name }}
</label>
<div class="select">
<select id="Option-{{ section.id }}-{{ forloop.index0 }}"
class="select__select"
name="options[{{ option.name | escape }}]"
form="{{ product_form_id }}"
>
{%- for value in option.values -%}
<option value="{{ value | escape }}" {% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-selects>
{%- endunless -%}
<noscript class="product-form__noscript-wrapper-{{ section.id }}">
<div class="product-form__input{% if product.has_only_default_variant %} hidden{% endif %}">
<label class="form__label" for="Variants-{{ section.id }}">{{ 'products.product.product_variants' | t }}</label>
<div class="select">
<select name="id" id="Variants-{{ section.id }}" class="select__select" form="{{ product_form_id }}">
{%- for variant in product.variants -%}
<option
{% if variant == product.selected_or_first_available_variant %}selected="selected"{% endif %}
{% if variant.available == false %}disabled{% endif %}
value="{{ variant.id }}"
>
{{ variant.title }}
{%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
- {{ variant.price | money | strip_html }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
</noscript>
Hope it helps!
This is an accepted solution.
Hi @Online_Seller,
Please change all code:
{%- when 'variant_picker' -%}
{%- unless product.has_only_default_variant -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}
<fieldset class="js product-form__input {% unless forloop.first %}hidden{% endunless %}">
<legend class="form__label">{{ option.name }}</legend>
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="{{ product_form_id }}"
{% if option.selected_value == value %}checked{% endif %}
>
<label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}">
{{ value }}
</label>
{%- endfor -%}
</fieldset>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-radios>
<variant-selects class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}
<div class="product-form__input product-form__input--dropdown {% if forloop.first %}hidden{% endif %}">
<label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}">
{{ option.name }}
</label>
<div class="select">
<select id="Option-{{ section.id }}-{{ forloop.index0 }}"
class="select__select"
name="options[{{ option.name | escape }}]"
form="{{ product_form_id }}"
>
{%- for value in option.values -%}
<option value="{{ value | escape }}" {% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-selects>
{%- endunless -%}
<noscript class="product-form__noscript-wrapper-{{ section.id }}">
<div class="product-form__input{% if product.has_only_default_variant %} hidden{% endif %}">
<label class="form__label" for="Variants-{{ section.id }}">{{ 'products.product.product_variants' | t }}</label>
<div class="select">
<select name="id" id="Variants-{{ section.id }}" class="select__select" form="{{ product_form_id }}">
{%- for variant in product.variants -%}
<option
{% if variant == product.selected_or_first_available_variant %}selected="selected"{% endif %}
{% if variant.available == false %}disabled{% endif %}
value="{{ variant.id }}"
>
{{ variant.title }}
{%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
- {{ variant.price | money | strip_html }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
</noscript>
Hope it helps!
Exactly what I was trying to achieve.
Thanks!!
Online_Seller
Would love to know how this code works. It changes the first, but the other 2 options are drop downs. Would love to know so the first 2 options could be radio buttons and the last could be checkmarks.
@LitCommerce Soo.....
It turns out that this doesn't work after all.
Whilst it solves the 'product is unavailable' issue the variants that are returned are not correct.
The two sections are acting independently of each other. The radio/buttons/pill for the first section at acting independent of the dropdown.
Updating the field then makes that section override the selection, which means that the hidden fields in each section are overriding the selected field from the other section.
IE
changing option 1 makes option 2 change to default (but doesn't appear to the user to be doing so)
AND
changing option 2 makes option 1 change to default (but doesn't appear to the user to be doing so)
But in each case it appears to the user that their selections are chosen, but in reality it is taking either option 1 or option 2 value from the hidden field.
They don't realise and then put this item in the basket.
EEK... HELP!
Online_Seller
This code not properly work changes the value of option in dropdown but in radio it selected only first option
Yes, I am also facing the same situation. Maybe the problem is with the Dawn version, not the code. Recently Dawn 13 has been released and it doesn't have any "variant-radios". Everything is within "variant-selects". Now, this functionality can be achieved very easily.
use this code this works properly
{%- unless product.has_only_default_variant -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}
<fieldset class="js product-form__input {% unless forloop.first %}hidden{% endunless %}">
<legend class="form__label">{{ option.name }}</legend>
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="{{ product_form_id }}"
data-handle="trigger-input"
{% if option.selected_value == value %}checked{% endif %}
>
<label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}">
{{ value }}
</label>
{%- endfor -%}
</fieldset>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-radios>
<variant-selects class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }} data-update-url="false">
{%- for option in product.options_with_values -%}
<div class="product-form__input product-form__input--dropdown {% if forloop.first %}hidden{% endif %}">
<label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}">
{{ option.name }}
</label>
<div class="select">
<select id="Option-{{ section.id }}-{{ forloop.index0 }}"
class="select__select"
name="options[{{ option.name | escape }}]"
form="{{ product_form_id }}"
data-handle="trigger-select"
>
{%- for value in option.values -%}
<option value="{{ value | escape }}" {% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
{%- endfor -%}
<script type="application/json">
{{ product.variants | json }}
</script>
</variant-selects>
{%- endunless -%}
<noscript class="product-form__noscript-wrapper-{{ section.id }}">
<div class="product-form__input{% if product.has_only_default_variant %} hidden{% endif %}">
<label class="form__label" for="Variants-{{ section.id }}">{{ 'products.product.product_variants' | t }}</label>
<div class="select">
<select name="id" id="Variants-{{ section.id }}" class="select__select" form="{{ product_form_id }}">
{%- for variant in product.variants -%}
<option
{% if variant == product.selected_or_first_available_variant %}selected="selected"{% endif %}
{% if variant.available == false %}disabled{% endif %}
value="{{ variant.id }}"
>
{{ variant.title }}
{%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
- {{ variant.price | money | strip_html }}
</option>
{%- endfor -%}
</select>
{% render 'icon-caret' %}
</div>
</div>
</noscript>
<script>
for (let i = 0; i < 3; i++) {
$('input[data-handle="trigger-input"][name="Color"]').click((e) => {
const value = e.currentTarget.value;
$('select[data-handle="trigger-select"][name="options[Color]"]').val(value )
});
}
$('select[data-handle="trigger-select"][name="options[Size]"]').change((e) => {
const value = e.currentTarget.value;
$(`input[type="radio"][name="Size"][value="${value}"]`).trigger("click")
});
</script>
This must be a fairly common need, and I have had a hard time finding a solution that works by googling. Therefore, here is a simple solution that I have come up with, even though it has been two years since the question was asked:
I am using Dawn and solved it by, firstly, setting Variant picker Style to Dropdown and then, secondly, editing the product-variant-picker.liquid snippet, using forloop.first to render the first option as pills.
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