Displaying variants options in collection page shopify - html

I know this question was asked million times on the internet but it seems like everyone wants to have a solution with their own twist. I can't find what I need exactly.
So I used this code to display variants on my collection and then to add to cart.
<form action="/cart/add" method="post" style="text-align:center;">
<select name="id">
{% for variant in product.variants %}
{% if variant.available %}
<option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - Sold Out</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Add to cart" class="btn" />
</form>
This works but in the dropdown, it gives it to me like this:
xs / Black - $72.00
small / Black - $61.00
medium / Black - $52.00
large / Black - $74.00
xl / Black - $77.00
xxl / Black - $55.00
xs / Blue - $72.00
small / Blue - $72.00
medium / Blue - $72.00
xl / Blue - $72.00
xxl / Blue - $72.00
What I want is for the customer to select size and color separately in different dropdowns and then click add to cart.
I was looking everywhere on how to do this with no luck. Please help.
My Shopify theme is Debut if it helps.

To obtain it in separate blocks, you must iterate on the product options, which are maximum 3, so you can show size and color separately.
{% unless product.has_only_default_variant %}
{% 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 style="display:block" 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 %}
{% endunless %}

You can do something like this:
<form action="/cart/add" method="post" style="text-align:center;">
<select name="id" id="{{ product.handle }}" style="display: none;">
{% for variant in product.variants %}
{% if variant.available %}
<option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - Sold Out</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Add to cart" class="btn" />
</form>
And you add the script at the end of the page:
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
<script>
var all_products = { {% for product in collection.products %}'{{ product.handle }}': {{ product | json }},{% endfor %} };
for(curr_product in all_products){
new Shopify.OptionSelectors(curr_product, {
product: all_products[curr_product]
});
}
</script>
We are relying on the Shopify function new Shopify.OptionSelectors that will split each select in a separate selects. Don't forget to add the id="{{ product.handle }}" to the main select.
Whole code:
{%- for product in collection.products -%}
<form action="/cart/add" method="post" style="text-align:center;">
<select name="id" id="{{ product.handle }}" style="display: none;">
{% for variant in product.variants %}
{% if variant.available %}
<option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - Sold Out</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Add to cart" class="btn" />
</form>
{% endfor %}
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
<script>
var all_products = { {% for product in collection.products %}'{{ product.handle }}': {{ product | json }},{% endfor %} };
for(curr_product in all_products){
new Shopify.OptionSelectors(curr_product, {
product: all_products[curr_product]
});
}
</script>

Related

Send the value of a disabled select in a form with a hidden input

I have a Django form, one of the parts is populated like this:
<select
{% if 'ba1' in widget.name or 'bs1' in widget.name or 'pm2' in widget.name %}
disabled
{% endif %}
id="{{ widget.attrs.id }}"
name="{{ widget.name }}"
{% if widget.attrs.disabled %}disabled{% endif %}
{% if widget.required %}required{% endif %}
class="form-control form-control-sm
{% if widget.errors %} is-invalid{% else %} is-valid{% endif %}"
aria-describedby="{{ widget.id }}-help">
{% for value, label in widget.attrs.choices %}
{% if value in widget.value %}
<option value="{{ value }}" selected>{{ label }}</option>
{% else %}
<option value="{{ value }}" data="{{widget.value}}">{{ label }}</option>
{% endif %}
{% endfor %}
</select>
As it is a disabled field for ba1, bs1 and pm2 cases, that information will not be sent in the POST request.
So what I have done is, through a hidden input, send the selected value of the disabled select.
Unfortunately the value is always 0 instead of the correct value. I'm doing something wrong. Somebody could help me?.
For example if the selected value is 2, or 3 or 4, it doesn't matter, the hidden input says that the selected value is 0, which is not correct.
Hidden input code (not working, always value = 0)
{% if 'ba1' in widget.name or 'bs1' in widget.name or 'pm2' in widget.name %}
<input
type="hidden"
name="{{ widget.name }}"
class="form-control form-control-sm
{% if widget.errors %} is-invalid{% else %} is-valid{% endif %}"
{% for value, label in widget.attrs.choices %}
{% if value in widget.value %}
value="{{ value }}"
{% else %}
value="{{ value }}" data="{{widget.value}}"
{% endif %}
{% endfor %}
>
{% endif %}
You can try setting the field as disabled in the init method of that Form class in forms.py.
def __init__(self, *args, **kwargs):
super(YourForm, self).__init__(*args, **kwargs)
self.fields['Yourfield'].disabled = True

HTML radio button is selecting multiple buttons although 'name' attribute has the same value

I googled for this, and the radio button should have the same 'name' attribute to allow only a single value to be chosen.
So I did, and It's still allowing me to choose multiple values...
I used HTML and Jinja2 templates for this, so the code might be looking a bit strange..
{% if search_keyword == None: %}
<p>Please enter your search keyword</p>
{% else: %}
{% for i in range(0, 10) %}
<form method="POST" action="./search">
<h2>
<input type="radio" name="selected_food" id="{{ i }}" value="{{ search_data["hits"][i]['recipe']['label'] }}">
{{ search_data["hits"][i]['recipe']['label'] }}
</h2>
<h4>
Calroies: {{ '%0.2f'| format(search_data["hits"][i]['recipe']['calories']) }} kcal
</h4>
{% for j in range(0, 40) %}
<p>{{ search_data['hits'][i]['recipe']['ingredientLines'][j] }}</p>
{% endfor %}
</form>
{% endfor %}
{% endif %}
In the above code the loop is creating multiple forms. This is the reason why you're able to select multiple values in radio.
If you can modify your code like this, it will work
{% if search_keyword == None: %}
<p>Please enter your search keyword</p>
{% else: %}
<form method="POST" action="./search">
{% for i in range(0, 10) %}
<div>
<h2>
<input type="radio" name="selected_food" id="{{ i }}" value="{{ search_data["hits"][i]['recipe']['label'] }}">
{{ search_data["hits"][i]['recipe']['label'] }}
</h2>
<h4>
Calroies: {{ '%0.2f'| format(search_data["hits"][i]['recipe']['calories']) }} kcal
</h4>
{% for j in range(0, 40) %}
<p>{{ search_data['hits'][i]['recipe']['ingredientLines'][j] }}</p>
{% endfor %}
</div>
{% endfor %}
</form>
{% endif %}

How to get Separate Drop Down for Color and Size on collection page in Shopify?

I want to Separate Drop Down for Color and Size under the product. Also if products is not available cart button should be disabled. Below is my code but I get both color and size in one dropdown.
<form action="/cart/add" method="post">
{% if product.variants.size == 1 %}
<input type="hidden" name="id" value="{{ product.variants.first.id }}" />
{% else %}
<select name="id" style="display:none;">{% for variant in product.variants %}
<option value="{{ variant.id }}">{{ variant.title }}
</option>{% endfor %}
</select>
{% endif %}
<div><button type="submit" name="add" class="btn">Add to cart</button></div>
</form>
{% for option in product.options_with_values %}
<select class="option-selector {{option.name}}" data-var="{{forloop.index}}">
{% if product.available %}
{% for values in option.values %}
<option value="{{values}}">{{values}}</option>
{% endfor %}
{% endif %}
</select>
{% endfor %}

If.-Value in a for loop: adding selected

Want to add the attribute "selected" to this select-field in my Django-Project:
<form id="formselect" method="post">
{% csrf_token %}
<select name="position_select" id="position_select">
<option value="0">all positions</option>
{% for position in position_options %}
<option value="{{ position.id }}"
{% if form.position.value == position.id.0 %} selected{% endif %}>
Position: {{ position.position_order }}
</option>
{% endfor %}
</select>
The result with this if method is that now every option is marked as selected in the output of that HTML. Is there a better way to handle that if-statement in a for loop?
I'm submitting this form on every click with:
$("#position_select").on("change", function() {
document.getElementById("formselect").submit();
});
You can try something like this:
{% for position in position_options %}
{% if form.position.value == position.id.0 %}
<option value="{{ position.id }}" selected>
{% else %}
<option value="{{ position.id }}" selected>
{% endif %}
Or:
<option value="{{ position.id }}" {{ form.position.value == position.id.0 ? "selected" : "" }}>

Multi-Filtering a collection of products

I'm trying to create multi-filters for my collections.
For example: In the first filter Drop Down list customers can pick MARVEL and in the second one I want them to see only MARVEL characters.
My questions are:
Which code do I need to write to get the value of the first drop down list?
Is it possible to generate a list of all products containing the tags MARVEL + another tag?
(I'm using the free theme 'Venture' if that helps somehow)
This is what my code currently looks like:
<div class="collection-sort">
<label for="SortTags" class="collection-sort__label">Universe</label>
<select name="SortTags" id="SortTags" class="collection-sort__input">
{% if collection.handle %}
<option value="/collections/{{ collection.handle }}">{{ 'collections.sorting.all_of_collection' | t }}</option>
{% elsif collection.current_type %}
<option value="{{ collection.current_type | url_for_type }}">{{ 'collections.sorting.all_of_collection' | t }}</option>
{% elsif collection.current_vendor %}
<option value="{{ collection.current_vendor | url_for_vendor }}">{{ 'collections.sorting.all_of_collection' | t }}</option>
{% endif %}
{% assign tags = 'MARVEL,DC,Games,Movies,TV' | split: ',' %}
var test;
{% for tag in tags%}
<option value="/collections/{% if collection.handle != blank %}{{ collection.handle }}{% else %}all{% endif %}/{{ tag | handleize }}"{% if current_tags contains tag %} selected="selcted"{% endif %}>{{ tag }}</option>
{% endfor %}
</select>
</div>