Ecommerce Shopify WordPress Discussion

How to create color swatch for Product in Product List

On my main page I have a block with a product catalog and I need to display radio buttons with colors and sizes. I'm bringing out product-variant-picker snippet from Dawn. I need to style the color buttons to match this color. For this purpose I created a metafield. The problem is that I display the label of the radio button, but due to the fact that one size has one color, the same color is displayed twice, but when you add to the cart, everything is added correctly. The problem is in the metafield output. For example, a product has 4 colors and two sizes. That is, he has 8 options. And when I display the code below, I have 4 color buttons as it should be, but the first two are the same color and the second two are a different color. This is due to the fact that there are two variants of the same color. //product-variant-picker {%- unless product.has_only_default_variant -%} <variant-radios id="variant-radios-{{ section.id }}" class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {% if update_url == false %} data-update-url="false" {% endif %} > {%- for option in product.options_with_values -%} <fieldset class="js product-form__input"> {% render 'custom-product-variant-options', product: product, option: option %} </fieldset> {%- endfor -%} <script type="application/json"> {{ product.variants | json }} </script> </variant-radios> {%- endunless -%} //product-variant-options {%- liquid assign variants_available_arr = product.variants | map: 'available' assign variants_option1_arr = product.variants | map: 'option1' assign variants_option2_arr = product.variants | map: 'option2' assign variants_option3_arr = product.variants | map: 'option3' assign product_form_id = 'product-form-' | append: section.id -%} {%- for value in option.values -%} {%- liquid assign option_disabled = true for option1_name in variants_option1_arr case option.position when 1 if variants_option1_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif when 2 if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif when 3 if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == product.selected_or_first_available_variant.option2 and variants_option3_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif endcase endfor -%} <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 %} {% if option_disabled %} class="disabled" {% endif %} > {% if option.name == 'Color' %} <label class="color-swatch" style="background-color: {{ product.variants[forloop.index0].metafields.custom.color }}" for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" > </label> {% else %} <label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"> {{ value }} </label> {% endif %} {%- endfor -%} Run code snippetExpand snippet <ul class="products-with-filter__content-products grid product-grid grid--3-col-desktop" data-id="{{ section.id }}" > {%- paginate collections.all.products by section.settings.products_per_page -%} {% for product in collections.all.products %} <li> ... {% render 'product-variant-picker', product: product, product_form_id: product_form_id %} {%- render 'buy-buttons', product: product, product_form_id: product_form_id, section_id: section.id, show_pickup_availability: true -%} </li> {% endfor %} {%- endpaginate -%} </ul> Run code snippetExpand snippet Desired result What comes out
Tthis issue is happening because you need to get the variant correctly inside product-variant-options.liquid. The forloop.index0 represents the variant options not the variant itself. This causes you to refer an incorrect variant. Try the following code, this would get the correct variant by looping through the variant options. {%- liquid assign variants_available_arr = product.variants | map: 'available' assign variants_option1_arr = product.variants | map: 'option1' assign variants_option2_arr = product.variants | map: 'option2' assign variants_option3_arr = product.variants | map: 'option3' assign product_form_id = 'product-form-' | append: section.id -%} {%- for value in option.values -%} {%- liquid assign option_disabled = true for option1_name in variants_option1_arr case option.position when 1 if variants_option1_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif when 2 if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif when 3 if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == product.selected_or_first_available_variant.option2 and variants_option3_arr[forloop.index0] == value and variants_available_arr[forloop.index0] assign option_disabled = false endif endcase endfor -%} {% liquid assign variant_needed = null for variant in product.variants if variant.options contains value assign variant_needed = variant endif endfor %} <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 %} {% if option_disabled %} class="disabled" {% endif %} > {% if option.name == 'Color' %} <label class="color-swatch" style="background-color: {{ variant_needed.metafields.custom.color }}" for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" > </label> {% else %} <label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"> {{ value }} </label> {% endif %} {%- endfor -%}

December 30, 2023

TurboCommerce make the better internet purchasing globaly

Turbo Multi-language Translator

Make the better internet purchasing globaly

Turbosify SEO Speed Booster

5.0 (7) Free plan available
Get better conversions by improving store loading speed Installed

Turbo Multi-language Chat - AI Customer service in one hand

TurboCommerce make the better internet purchasing globaly
Our products

The help you need, when you need it

App by Turbo Engine

3 apps • 5.0 average rating

Turbosify Speed Booster

5.0 (7)
Get better conversions by optimizing shopify store Google page speed Installed

Turbosify Translator for Wordpress Woocommerce

5.0 (74) Free Wordpress Woocommerce Plugin
Translate your wordpress website to multiple language within 1 click, no configuration needed, no No technical required

Grow your business here

Whether you want to sell products down the street or around the world, we have all the tools you need.