Transform Dropdown Selectors to Product Swatches in the IO Bundle
By default, the IO bundle's selectors appear as dropdown menus. However, you can choose to display these selectors as product swatches instead. This guide will take you through the necessary steps to achieve this.
Expected Output:
Prerequisites
Before starting, make sure you have manually set up infinite options by following these guides:
Setup Instructions for Online Store 2.0
1. Create a Product Template
- Create a product template of JSON type named
simple-bundles.json
. - Add the following snippet inside the sections:
"simple-bundles": { "type": "simple-bundles", "settings": {} }
- Add
"simple-bundles"
inside the order:
"simple-bundles"
2. Create a New Section
- Create a new section named
simple-bundles.liquid
. - Add the code from step 2 in this article.
3. Create a New Snippet
- Create a new snippet named
simple-bundles-options.liquid
. - Add the code from step 3 in this article.
4. Add Additional Snippet Code
- Add the snippet from this to the end of
simple-bundles-options.liquid
.
5. Assign Template to Product
- Assign the bundle’s template on the product admin to
simple-bundles
.
Optional: Multiple Options in Option Groups
If you have multiple options within option groups, replace the code from the simple-bundles.liquid
with the code provided here: https://gist.github.com/basilkhan05/06fc47bf764fc02d24c53b4670f63b80
Adding Images for Swatches
The next steps are the instructions to create a metaobjects, which we will utilize to be displayed in the IO bundles.
1. Create Metaobject Definition
- Navigate to your store settings and add a metaobject definition under Custom Data named
product-swatches
.
2. Configure Fields
- Inside the
product-swatches
metaobject definition, add a field namedoption-name
with appropriate configuration.
- Add another field named
option-image
with appropriate configuration.
3. Add Metaobject Entries
- Add entries to the metaobjects that match the options configured in your bundle.
- Ensure the
option-name
field value matches the option name in your bundle.
- Upload the desired image for each option.
Replace Snippet Code
Replace the code in simple-bundles-options.liquid
with the following:
<style> .variant-input-wrap label { margin-bottom: 0 !important; } .variant__button-label-swatches{ width: 35px; height: 35px; background-size: cover; } .variant-input-wrap { display: flex; align-content: stretch; flex-wrap:wrap; border: none; justify-content: center; } .variant-input-wrap input{ border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .variant-input-wrap label { position: relative; display: inline-block; font-weight: 400; padding: 7px 15px; margin: 0 8px 12px 0; background-color: #fff; box-shadow: 0 0 0 1px #231f20; overflow: hidden; } </style> <div id="{{ div_id }}"> {% for variant_option in variant.metafields.simple_bundles.variant_options.value %} {% assign option_name_param = variant_option.optionName | downcase | replace: " ", "-" | strip | append: "-" | append: forloop.index %} <strong>{{ variant_option.optionName }}</strong><br /> {% assign option_values = variant_option.optionValues | split: "," %} {% assign option_inventories = variant_option.optionInventories | split: "," %} <fieldset class="variant-input-wrap"> {% for option_value in option_values %} {% assign option_value_param = option_value | downcase | replace: " ", "-" | strip %} {% assign value = option_value | strip %} {% assign radio_param = option_name_param | append: "-" | append: option_value_param %} <div class="variant-input"> {% if option_inventories[forloop.index0] %} {% assign option_inventory = option_inventories[forloop.index0] | plus: 0 %} <input type="radio" id="{{ radio_param }}" name="properties[{{ variant_option.optionName }}]" value="{{ value }}" data-inventory="{{ option_inventory }}" {% if option_inventory < 1 %}disabled{% endif %} {% if forloop.index == 1 %}checked{% endif %} autocomplete="off" /> {% else %} <input type="radio" id="{{ radio_param }}" name="properties[{{ variant_option.optionName }}]" value="{{ value }}" {% if forloop.index == 1 %}checked{% endif %} autocomplete="off" /> {% endif %} {% assign titleMatches = false %} {% assign URLimage = "" %} {% paginate shop.metaobjects.product_swatches.values by 250 %} {% for color_item in shop.metaobjects.product_swatches.values %} {% assign valueDowncase = value | downcase%} {% assign colorItemDowncase = color_item.option_name| downcase %} {% if colorItemDowncase == valueDowncase %} {% assign titleMatches = true %} {% assign URLimage = color_item.option_image %} {% break %} {% endif %} {% endfor %} {% endpaginate %} {% if titleMatches %} <label class="variant__button-label variant__button-label-swatches" for="{{ radio_param }}" style="background: url({{ URLimage | image_url: width: 180, height: 180 }}); display: inline-block"></label><br/> {% else %} <label class="variant__button-label" for="{{ radio_param }}">{{ value }}</label><br /> {% endif %} </div> {% endfor %} </fieldset> {% endfor %} </div> <script> (function() { // function to update the hidden input value function updateHiddenInputValue() { var selects = document.querySelectorAll('#{{ div_id }} select'); var values = []; selects.forEach(function(select) { var selectedOption = select.options[select.selectedIndex]; if (selectedOption) { values.push(selectedOption.value); } }); if (values.length === 0) { return; } var hiddenInputValue = values.join(' <> '); var hiddenInput = document.querySelector('#{{ div_id }} input[name="properties[_bundle_selection]"]'); if (!hiddenInput) { hiddenInput = document.createElement('input'); hiddenInput.type = 'hidden'; hiddenInput.name = 'properties[_bundle_selection]'; document.getElementById('{{ div_id }}').appendChild(hiddenInput); } hiddenInput.value = hiddenInputValue; } // call the function initially to update the hidden input value window.addEventListener('pageshow', updateHiddenInputValue); // listen for changes on each select element and update the hidden input value var selects = document.querySelectorAll('#{{ div_id }} select'); selects.forEach(function(select) { select.addEventListener('change', updateHiddenInputValue); }); })(); </script>
CSS
This styles the variant selection elements to ensure a user-friendly interface. It ensures labels and inputs are appropriately sized, positioned, and styled for usability and desired layout. Note: This can vary from theme to theme. Kindly adjust or modify it accordingly.
Liquid Template
This iterates over product variant options and dynamically generates HTML elements for each option. It creates radio buttons for each variant value, incorporating inventory checks to disable out-of-stock options. It also matches variant values with predefined swatches and applies corresponding images from the metaobjects created to labels.
Note: On the Liquid code line in that file, containing {% paginate shop.metaobjects.product_images.values by 250 %}
, you can adjust the number depending on how many entries are in the product_images metaobject definition.
JavaScript
This updates the input field to group and fetch the selected options dynamically.
Need Help?
If you have any questions or need further assistance with setting this up, please feel free to contact our team. We are happy to help!