All things Shopify and commerce
For some reason when I select a variant the image does not change.
You can check it at this url - https://dotewellness.com/products/power
I attach my main-product.liquid in case you can help me.
<script>
const productJson = {{ product | json }};
if (productJson.type == "sample") {
window.location.href = "/";
Rebuy.SmartCart.view.show();
}
</script>
{{ 'section-main-product.css' | asset_url | stylesheet_tag }}
<script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script>
<style>
.rc-container-wrapper.rc_container_wrapper{
display:none;
}
</style>
<div id="shop" class="main-product {% if template.suffix contains 'bundle' %}bundle{% endif %}">
{%- assign product_form_id = 'product-form-' | append: section.id -%}
<div class="page-width product-page">
<ul class="product-images" style="grid-template-rows: repeat({{ product.media.size }}, 170px);">
{%- for media in product.media -%}
{%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
<li class="image-thumbnail {% if media.id == product.media.first.id %} active {% endif %}" data-image-url="{{ media.preview_image | img_url: 'master' }}" >
<img src="{{ media.preview_image | img_url: 'master' }}" loading="lazy" alt="{{ media.id }}" height="auto" width="auto" />
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
<div class="active-product-image">
<img src="{{ product.media[0] | img_url: 'master' }}" alt="{{ product.title }} - {{ product.metafields.descriptors.subtitle }}" loading="lazy" height="auto" width="auto" />
</div>
<div class="swipe-container">
<div class="swiper">
<ul class="swiper-wrapper">
{%- for media in product.media -%}
{%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
<li class="swiper-slide">
<div class="image-container">
<img src="{{ media.preview_image | img_url: 'master' }}" loading="lazy" alt="{{ media.id }}" height="auto" width="auto" />
</div>
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
<div class="swiper-pagination"></div>
</div>
</div>
<div class="product-content">
<div class="product-info">
<h1 class="title">{{ product.title }}</h1>
<h2 class="subtitle">{{ product.metafields.descriptors.subtitle }}</h2>
{% if section.settings.show_covid_disclaimer and section.settings.show_covid_before == true %}
{% render 'covid-disclaimer',
disclaimer: section.settings.covid_disclaimer,
background: section.settings.covid_background,
border: section.settings.covid_border,
font: section.settings.covid_font
%}
{% endif %}
{{ product.description }}
</div>
<div class="form-container">
<div class="form-text">
<h3 class="helps-with">Helps With</h3>
{% comment %} accentuate-here {% endcomment %}
<ul class="benefits">
{% for item in product.metafields.accentuate.helps_with_item %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if product.metafields.accentuate.badge_icon %}
<ul class="badges">
{% for badge in product.metafields.accentuate.badge_icon %}
<li class="badge">
<img src="{{ badge[0].src }}" loading="lazy" alt="{{ badge.alt }}" height="auto" width="auto" />
{% if product.metafields.accentuate.badge_subtext[forloop.index0] %}
<span>{{ product.metafields.accentuate.badge_subtext[forloop.index0] }}</span>
{% else %}
<span> </span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% if product.metafields.accentuate.verification_of_analysis %}
<a class="verification-url" href="{{ product.metafields.accentuate.verification_of_analysis }}" target="_blank">{{ section.settings.certificate_heading }}</a>
{% endif %}
</div>
<product-form>
{%- form 'product', product, data-productid: product.id, id: product_form_id, class: 'form', novalidate: 'novalidate', data-type: 'add-to-cart-form' -%}
{% if product.variants.size == 1 %}
<input type="hidden" name="id" data-productid="{{ product.id }}" value="{{ product.selected_or_first_available_variant.id }}" disabled>
{% endif %}
<div class="options">
{% unless product.variants.size == 1%}
<div class="form_group">
<label>Size</label>
<div class="select">
<select name="id" data-productid="{{ product.id }}" id="Variants-{{ section.id }}" class="select__select variant-selector" 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 }} - {{variant.price | money}}
{%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{%- endfor -%}
</select>
</div>
</div>
{% endunless %}
<div class="form_group">
<label>Qty</label>
<quantity-input class="quantity">
<button class="quantity__button no-js-hidden" name="minus" type="button">
<span class="visually-hidden">{{ 'products.product.quantity.decrease' | t: product: product.title | escape }}</span>
{% render 'icon-minus' %}
</button>
<input class="quantity__input"
type="number"
name="quantity"
id="Quantity-{{ section.id }}"
min="1"
max="{{ product.selected_or_first_available_variant.inventory_quantity }}"
value="1"
form="product-form-{{ section.id }}"
>
<button class="quantity__button no-js-hidden" name="plus" type="button">
<span class="visually-hidden">{{ 'products.product.quantity.increase' | t: product: product.title | escape }}</span>
{% render 'icon-plus' %}
</button>
</quantity-input>
</div>
</div>
{% if product.selling_plan_groups.size > 0 %}
<div class="radios">
<label class="radio-container active" for="OneTimeInput">
<input id="OneTimeInput" name="sub-select" type="radio" name="purchase_type" data-type="onetime" value="onetime" checked />
<div class="custom-radio">
<span></span>
<p>One time purchase - <span class="product-price-line">{{ product.selected_or_first_available_variant.price | money }}</span></p>
</div>
</label>
<label class="radio-container" for="rc_purchase_type_autodeliver">
<input name="sub-select" type="radio" name="purchase_type" data-type="subsave" id="rc_purchase_type_autodeliver" value="autodeliver" />
<div class="custom-radio">
<span></span>
{% assign rechargePrice = product.selected_or_first_available_variant.price | times: product.selling_plan_groups[0].selling_plans[0].price_adjustments[0].value | divided_by: 100 %}
<div>
<p>
Subscribe & Save. - <span class="product-price-line">{{ product.selected_or_first_available_variant.price | minus: rechargePrice | money }}</span>
</p>
<p style="max-width: 300px;font-size:12px">
(Receive free delivery and your sixth
bottle at no charge. <a href="https://dotewellness.com/pages/subscribe">Pause, skip, or cancel anytime.</a>)
</p>
</div>
</div>
<div class="select">
<select id="main_selling_plan" name="main_selling_plan" class="select__select">
{% for product in product.selling_plan_groups %}
{% for plan in product.selling_plans %}
<option data-plan-option="{{ plan.name }}" value="subsave-{{ plan.id }}">{{ plan.name }}</option>
{% endfor %}
{% endfor %}
</select>
</div>
</label>
</div>
{% else %}
{%- for variant in product.variants -%}
{% if product.title contains 'Calm' or product.title contains 'Power'%}
{% else %}
<div style="margin-bottom: 10px ">{{ product.price | money }}</div>
{% endif %}
{% endfor %}
{% endif %}
<button
type="submit"
name="add"
class="product-form__submit button {% if product.selling_plan_groups == empty %}button--secondary{% else %}button--primary{% endif %}"
{% if product.selected_or_first_available_variant.available == false %}disabled{% endif %}
>
<span>
{%- if product.selected_or_first_available_variant.available -%}
{{ 'products.product.add_to_cart' | t }}
{%- else -%}
{{ 'products.product.sold_out' | t }}
{%- endif -%}
</span>
<div class="loading-overlay__spinner hidden">
<svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle>
</svg>
</div>
</button>
<div class="product-form__error-message-wrapper">
<p class="product-form__error-message"></p>
</div>
{%- endform -%}
</product-form>
</div>
<p class="fda">
{{ section.settings.fda_statement }}
</p>
<button type="button" class="back-to-top" aria-label="Back to Top">
<svg viewBox="0 0 24 24" class="Icon__IconComponent-xohm6-0 jdqSGx"><path transform="rotate(-90 12 12)" d="M9.672 15.47a.615.615 0 0 0 0 .853c.23.236.602.236.832 0l3.824-3.896a.615.615 0 0 0 0-.854l-3.824-3.896a.578.578 0 0 0-.832 0 .615.615 0 0 0 0 .853L13.08 12l-3.408 3.47z"></path></svg>
</button>
</div>
</div>
<div class="footer-dock">
<div class="page-width">
<div class="product-image">
<img src="{{ product.media[0].preview_image | img_url: 'master' }}" alt="{{ product.title }}" loading="lazy" height="auto" width="auto">
</div>
{%- assign product_dock_form_id = 'product-dock-form-' | append: section.id -%}
<product-form>
{%- form 'product', product, data-productid: product.id, id: product_dock_form_id, class: 'form', novalidate: 'novalidate', data-type: 'add-to-cart-form' -%}
<input type="hidden" name="id" data-productid="{{ product.id }}" value="{{ product.selected_or_first_available_variant.id }}" disabled>
<div class="inject"></div>
<div class="form_group" {% if product.variants.size == 1 %}style="display:none"{% endif %}>
<label>{{ product.title }} {{ product.metafields.descriptors.subtitle }}</label>
<div class="select">
<select name="id" data-productid="{{ product.id }}" id="dock-Variants-{{ section.id }}" class="select__select" form="{{ product_dock_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 %}
</option>
{%- endfor -%}
</select>
</div>
</div>
{% if product.selling_plan_groups.size > 0 %}
<div class="form_group">
<label>Frequency</label>
<div class="select frequency">
<input type="radio" name="purchase_type" data-type="onetime" value="onetime" checked hidden />
<input type="radio" name="purchase_type" data-type="subsave" id="rc_purchase_type_autodeliver" value="autodeliver" hidden />
<select id="dock_selling_plan" class="select__select" name="dock_selling_plan">
<option value="onetime">One Time Purchase</option>
{% for product in product.selling_plan_groups %}
{% for plan in product.selling_plans %}
<option data-plan-option="{{ plan.name }}" value="subsave-{{ plan.id }}">{{ plan.name }}</option>
{% endfor %}
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="form_group">
<label for="dock-Quantity-{{ section.id }}">Qty</label>
<quantity-input class="quantity">
<button class="quantity__button no-js-hidden" name="minus" type="button">
<span class="visually-hidden">{{ 'products.product.quantity.decrease' | t: product: product.title | escape }}</span>
{% render 'icon-minus' %}
</button>
<input class="quantity__input"
type="number"
name="quantity"
id="dock-Quantity-{{ section.id }}"
min="1"
value="1"
form="product-dock-form-{{ section.id }}"
>
<button class="quantity__button no-js-hidden" name="plus" type="button">
<span class="visually-hidden">{{ 'products.product.quantity.increase' | t: product: product.title | escape }}</span>
{% render 'icon-plus' %}
</button>
</quantity-input>
</div>
<button
type="submit"
name="add"
class="product-form__submit button {% if product.selling_plan_groups == empty %}button--secondary{% else %}button--primary{% endif %}"
{% if product.selected_or_first_available_variant.available == false %}disabled{% endif %}
>
<span>
{%- if product.selected_or_first_available_variant.available -%}
{{ 'products.product.add_to_cart' | t }}
{%- else -%}
{{ 'products.product.sold_out' | t }}
{%- endif -%}
</span>
<div class="loading-overlay__spinner hidden">
<svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle>
</svg>
</div>
</button>
<div class="product-form__error-message-wrapper">
<p class="product-form__error-message"></p>
</div>
{%- endform -%}
<product-form>
</div>
</div>
</div>
{% schema %}
{
"name": "t:sections.main-product.name",
"tag": "section",
"class": "product-section",
"blocks": [
{
"type": "@app"
},
{
"type": "quantity_selector",
"name": "t:sections.main-product.blocks.quantity_selector.name",
"limit": 1
},
{
"type": "variant_picker",
"name": "t:sections.main-product.blocks.variant_picker.name",
"limit": 1,
"settings": [
{
"type": "select",
"id": "picker_type",
"options": [
{
"value": "dropdown",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.options__1.label"
},
{
"value": "button",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.options__2.label"
}
],
"default": "button",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.label"
}
]
},
{
"type": "badge",
"name": "Badge",
"settings": [
{
"type": "text",
"id": "title",
"label": "Title",
"info": "Text under badge icon"
},
{
"type": "text",
"id": "type",
"label": "type",
"info": "Type must match product's tag"
},
{
"type": "image_picker",
"id": "badge_image",
"label": "Badge Image"
}
]
},
{
"type": "verification",
"name": "Verification",
"settings": [
{
"type": "text",
"id": "title",
"label": "Text",
"default": "View Verification of analysis"
},
{
"type": "url",
"id": "url",
"label": "URL"
}
]
}
],
"settings": [
{
"type": "text",
"label": "FDA Statement",
"id": "fda_statement",
"default": "*These statements have not been evaluated by the Food and Drug Administration. This product is not intended to diagnose, treat, cure or prevent any disease."
},
{
"type": "text",
"label": "Certificate of Analysis Heading",
"id": "certificate_heading",
"default": "View Certificate Of Analysis"
},
{
"type": "checkbox",
"label": "Covid Disclaimer Before Description",
"id": "show_covid_before",
"default": false
},
{
"type": "checkbox",
"label": "Show Covid Disclaimer Border",
"id": "covid_border",
"default": true
},
{
"type": "color",
"label": "Covid Disclaimer Background Color",
"id": "covid_background"
},
{
"type": "checkbox",
"label": "Covid Disclaimer Large Font",
"id": "covid_font",
"default": false
},
{
"type": "richtext",
"label": "Covid Shipping Disclaimer",
"id": "covid_disclaimer",
"default": "<p>DUE TO SUPPLY CHAIN SHORTAGES OF COVID-19, THIS PRODUCT WILL BE SHIPPED IN OUR SUSTAINABLE PACKAGING FOR A DISCOUNTED OFFER.</p>"
}
]
}
{% endschema %}
<style>
.product-price-line {
all: unset !important;
}
.product-price-line:before {
display: none;
all: unset;
}
.swiper-wrapper {
transition: all 0.3s !important;
}
</style>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js" defer="defer"></script>
<script>
// variant updater
const variantSelector = document.querySelector(".variant-selector");
const priceContainer = document.querySelector(".product-price-line");
if (variantSelector) {
variantSelector.addEventListener("change", async (e) => {
const data = await fetch(`/variants/${e.target.value}.json`).then(res => res.json());
priceContainer.innerText = `$${data.product_variant.price}`
})
}
// scroll to top on load
var productImagesSwiper = new Swiper(".main-product .swiper", {
spaceBetween: 0,
centeredSlides: true,
variableWidth : true,
loop: true,
slidesPerView: 1,
pagination: {
el: ".main-product .swiper-pagination",
clickable: true
}
});
const swiperWrapper = document.querySelector(".swiper-wrapper");
productImagesSwiper.on("imagesReady", () => {
const activeSlide = document.querySelector(".swiper-slide-active .image-container img");
if (activeSlide) {
swiperWrapper.style.height = `${activeSlide.scrollHeight + 20}px`;
}
})
productImagesSwiper.on("slideChangeTransitionEnd", () => {
const activeSlide = document.querySelector(".swiper-slide-active .image-container img");
if (activeSlide) {
swiperWrapper.style.height = `${activeSlide.scrollHeight + 20}px`;
}
})
// handle thumbnail clicks
const imgBank = document.querySelector(".product-images");
var thumbnails = document.querySelectorAll('.main-product .product-images .image-thumbnail');
thumbnails.forEach(function(thumbnail, index) {
const scrollPoint = 1 / thumbnails.length * imgBank.scrollHeight * (index - 1);
thumbnail.addEventListener('click', function() {
thumbnails.forEach(function(t) {
if (t.classList.contains('active')) {
t.classList.remove('active');
}
})
var target = document.querySelector('.main-product .active-product-image img');
target.src=thumbnail.dataset.imageUrl;
thumbnail.classList.add('active');
imgBank.scrollTo({
top: scrollPoint,
behavior: "smooth"
})
})
})
var productNavLinks = document.querySelectorAll('.page-width.product-page-navigation li a');
var pageNavigationDock = document.querySelector('.page-width.product-page-navigation');
productNavLinks.forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
const id = `${e.target.attributes['href'].nodeValue}`;
const yOffset = pageNavigationDock.offsetHeight * -1;
const element = document.getElementById(id.split('#').join(''));
const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;
window.scrollTo({top: y, behavior: 'smooth'});
})
});
var customRadios = document.querySelectorAll('.main-product .product-page .radios .radio-container input');
var frequencySelect = document.querySelector('.main-product .product-page .radios .radio-container .select select');
customRadios.forEach(function(btn) {
btn.addEventListener('click', function() {
var selectContainer = document.querySelector('.main-product .product-page .radios .radio-container .select');
if (document.querySelectorAll('.form-container .rc-radio__input').length > 0) {
var rcInputs = document.querySelectorAll('.form-container .rc-radio__input');
rcInputs.forEach(function(input) {
if (btn.dataset.type === input.value) {
input.click();
}
})
}
customRadios.forEach(function(b) {
b.parentElement.classList.remove('active');
});
if (btn.dataset.type === 'subsave') {
selectContainer.style.maxHeight = selectContainer.scrollHeight + 'px';
selectContainer.style.opacity = '1';
} else {
selectContainer.style.opacity = '0';
selectContainer.style.maxHeight = '0px';
frequencySelect.selectedIndex = 0;
}
btn.parentElement.classList.add('active');
})
});
frequencySelect.addEventListener('change', function(e) {
var rcInputs = document.querySelectorAll('.form-container .rc-radio__input');
var rcSelect = document.querySelector('.form-container .rc_widget select');
var rcSelectOptions = document.querySelectorAll('.form-container .rc_widget select option');
rcInputs.forEach(function(input) {
var type = e.target.value.split('-')[0];
var value = e.target.value.split('-')[1];
if (type === input.value) {
input.click();
rcSelectOptions.forEach(function(option, i) {
if (value === option.value) {
rcSelect.selectedIndex = i;
}
});
}
})
})
var footerFrequency = document.querySelector('.footer-dock .frequency select');
footerFrequency.addEventListener('change', function(e) {
var rcInputs = document.querySelectorAll('.footer-dock .rc-radio__input');
var rcSelect = document.querySelector('.footer-dock .rc_widget select');
var rcSelectOptions = document.querySelectorAll('.footer-dock .rc_widget select option');
rcInputs.forEach(function(input) {
var type = e.target.value.split('-')[0];
var value = e.target.value.split('-')[1];
if (type === input.value) {
input.click();
rcSelectOptions.forEach(function(option, i) {
if (value === option.value) {
rcSelect.selectedIndex = i;
}
});
}
})
})
document.addEventListener('DOMContentLoaded', () => {
var checkExist = setInterval(function() {
if (document.querySelector('.inject').children.length === 0) {
if (ReChargeWidget !== undefined) {
var productId = "{{ product.id }}";
ReChargeWidget.createWidget({ productId: Number(productId), injectionParent: '.inject' });
clearInterval(checkExist);
}
}
}, 500);
});
</script>
<script type="text/javascript">
var _learnq = _learnq || [];
var item = {
Name: {{ product.title | json }},
ProductID: {{ product.id | json }},
Categories: {{ product.collections | map: 'title' | json }},
ImageURL: "https:{{ product.featured_image.src | img_url: 'grande' }}",
URL: "{{ shop.secure_url }}{{ product.url }}",
Brand: {{ product.vendor | json }},
Price: {{ product.price | money | json }},
CompareAtPrice: {{ product.compare_at_price_max | money | json }}
};
_learnq.push(['track', 'Viewed Product', item]);
_learnq.push(['trackViewedItem', {
Title: item.Name,
ItemId: item.ProductID,
Categories: item.Categories,
ImageUrl: item.ImageURL,
Url: item.URL,
Metadata: {
Brand: item.Brand,
Price: item.Price,
CompareAtPrice: item.CompareAtPrice
}
}]);
document.querySelectorAll(".product-form__submit").forEach(btn => {
btn.addEventListener('click', () => {
_learnq.push(['track', 'Added to Cart', item]);
})
})
</script>
Hi @AJRAToni,
I had a look at your store and it seems that you may have resolved the issue yourself, as the variant images do in fact change every time I click on them.
For future reference, we have a guide to Adding Images to Product Variants that walks you through exactly what you want to achieve, without the need for making code edits to your theme!
What kind of theme are you using? And what kind of brand are you building? I'd love to learn more about what you see as the future of your business!
To learn more visit the Shopify Help Center or the Community Blog.
When you click on the images it changes, but when you select a variant from the dropdown the image doesn't change.
I want it to change when the variant is selected from the dropdown.
Are you referring to the dropdown in your main menu?
If so, what image is displayed depends very much on what product or collection you have linked to that menu item. You cannot link variants, because as explained in our guide Add, remove, or edit menu items in your online store: "Menu items are links to products, collections, webpages, blog posts, policies, or other websites."
So each supplement would need to be a different product with a different image, and each individual product would have to be linked to the respective menu item in the dropdown.
I hope that makes sense!
To learn more visit the Shopify Help Center or the Community Blog.
Sorry, I think I didn't explain myself well.
This product has two variants each with an image.
When I select a variant the image does not change, it always shows the same one.
I think it's because of this, but I don't know what I should change.
<div class="active-product-image">
<img src="{{ product.media[0] | img_url: 'master' }}" alt="{{ product.title }} - {{ product.metafields.descriptors.subtitle }}" loading="lazy" height="auto" width="auto" />
</div>
It seems I understood your query the first time around: you have a product with variants, and each variant has its own image. You want the image to change whenever a visitor clicks on a different variant. That's why I linked you to the relevant guide: Adding Images to Product Variants.
Of course, this may not work if you're using a third-party heavily customized theme, which is why I keep asking you what theme it is you're using - if you could answer that question and also tell me whether you've made a lot of code edits to your theme, it would really help me to help you!
To learn more visit the Shopify Help Center or the Community Blog.
Am I correct in understanding that I can only assign one image per variant?
Hi,
I have the same problem u did. So i wonder if u fixed this and how u did it.
Greets
I believe the issue is in your code, product.media[0] is a reference to the first variant image.
Here is the solution. FREE and without App.
You can try this tutorial:
We recently spoke with Zopi developers @Zopi about how dropshipping businesses can enha...
By JasonH Oct 23, 2024A big shout out to all of the merchants who participated in our AMA with 2H Media: Holi...
By Jacqui Oct 21, 2024We want to take a moment to celebrate the incredible ways you all engage with the Shopi...
By JasonH Oct 15, 2024