In the same way as the product variants SKUs can be displayed, I'd like to display our product variants metafield called "material". It's stored in variant.metafields.specs.material. How can I achieve this?
I was following https://help.shopify.com/en/themes/customization/products/features/show-sku-numbers
{% if variant.metafields.specs.material != blank %} <p>Material: {{ variant.metafields.specs.material }}</p> {% endif %}
This displays the metafield. But it's static, not dynamic like the SKU. When you select variant options (sizes and colors) the SKU changes. The "material" does not. Only if you reload the product page with the variant in the URL, only than the metafield data changes.
Here's the code for the SKU that works:
{% if variant.sku != blank and section.settings.display_sku %} <p class="sku">SKU: <span itemprop="sku">{{ variant.sku }}</span></p> {% endif %}
I assume the issue is in the selectCallback function in sections.js.liquid. There I see:
$('.sku span', $product).text(variant.sku);
So by analogy I added:
$('.material span', $product).text(variant.metafields.specs.material);
This broke the functionality of the product page and the variants select elements disappeared.
Any advice or suggestions?
Thanks,
Val
Solved! Go to the solution
@ValTodorov wrote:...This displays the metafield. But it's static, not dynamic like the SKU. When you select variant options (sizes and colors) the SKU changes. The "material" does not. Only if you reload the product page with the variant in the URL, only than the metafield data changes...
You're on the right track.
When a variant is picked on the front end - using whatever UI is in place - there'll be JavaScript that fires a function. That function will handle the changing of price and sku data.
For your metafield to also be shown you'll need to:
Jason, thanks for the tips. As you wrote "push them into the existing product object", I tried to add
$('.foo', $product).text(variant.metafields.specs.material);
in selectCallback after
selectCallback = function(variant, selector) { var $product = $('.product-' + selector.product.id); var $notify_form = $('.notify-form-' + selector.product.id); var $productForm = $('.product_form, .shopify-product-form', $product); var variantInventory = $productForm.data('variant-inventory'); if (variant) { if (variantInventory) { variantInventory.forEach(function(v){ if (v.id === variant.id) { variant.inventory_quantity = v.inventory_quantity; variant.inventory_management = v.inventory_management; variant.inventory_policy = v.inventory_policy; } }); } $('.sku span', $product).text(variant.sku);
It complains
TypeError: variant.metafields is undefined
But it doesn't seem to complain about variant.sku
Your thoughts?
This is an accepted solution.
Hi Val,
Jason pretty much explain the way to do it.
You need to:
1. Store the variant data in a JavaScript variable.
Can be something like this (not tested):
{% capture 'meta_data' %} {% for variant in product.variants %} {{ variant.sku | json }}: {{ variant.metafields.specs.material | json }} {% unless forloop.last %},{% endunless %} {% endfor %} {% endcapture %} <script> var metaData = { {{ meta_data }} } </script>
2. On selectCallback pull data from that metaData object based on the variant SKU and display it in your page.
selectCallback = function(variant, selector) { // ... your default selectCallback code here var material = metaData[variant.sku]; }
Hope it makes sense.
Thanks to Mircea, I was able to make it work.
Capturing the meta data in product-template.liquid worked exactly as described by him.
Then in the selectCallback function in sections.js.liquid I had to add:
$('.material span', $product).text(metaData[variant.sku]);
Then back in product-template.liquid I could display the meta data in the same way as the SKU:
{% if variant.sku != blank and section.settings.display_sku %} <p class="sku">SKU: <span itemprop="sku">{{ variant.sku }}</span></p> <p class="material">Material: <span itemprop="material">{{ variant.sku }}</span></p> {% endif %}
By the way, the theme I'm working with is Turbo Portland.
Thanks both to Jason and Mircea for the tips.
Hi Mircea
I have checked this code module, it helps me to display variant values where i wanted to display. Because there is a for loop, it displaying all the key_values of all variants.
Can you please help me to display single key_value at a time. So, when i switch to another variant then metafields or key_value also change immediately.
Here you can see my requirement, i have posted:
https://community.shopify.com/c/Technical-Q-A/Update-metafields-value-by-change-variant/m-p/658958/h...
Hi Mircea Piturca,
I used some parts of your code to add shipping info to each variant via metafield to a client's store. Here's a solution that doesn't involve the product/variantSKU
<p class="variant_shipping_info" style="display: none;"></p>
{% capture 'meta_data' %} {% for variant in product.variants %} {{variant.id}}:{{ variant.metafields.global.availability | json }}{% unless forloop.last %},{% endunless %} {% endfor %} {% endcapture %} <script> const currentVariantId = {{ product.selected_or_first_available_variant.id }}; // get the currently selected before variant is changed. const metaData = { {{ meta_data }} }; const shippingInfo = (id) => { var selector = document.querySelector('.variant_shipping_info'); if (metaData[id]) { selector.style.display = 'block' selector.innerHTML = metaData[id]; } } shippingInfo(currentVariantId);
// When the variant is changed, get the id and call the function. :) document.addEventListener('variant:changed', function(event) { var variant = event.detail.variant; // Gives you access to the whole variant details var id = variant.id shippingInfo(id); }); </script>
Hey Temitope! I've tried to apply this kind of code into my snippet which i am calling, unfortunately i have to reload my page to see the variant i have changed.
The only modification i've made is the key and namespace of the metafield variant:
<p class="variant_shipping_info" style="display: none;"></p> {% capture 'meta_data' %} {% for variant in product.variants %} {{variant.id}}:{{ variant.metafields.global.additionalinfo | json }}{% unless forloop.last %},{% endunless %} {% endfor %} {% endcapture %} <script> const currentVariantId = {{ product.selected_or_first_available_variant.id }}; // get the currently selected before variant is changed. const metaData = { {{ meta_data }} }; const shippingInfo = (id) => { var selector = document.querySelector('.variant_shipping_info'); if (metaData[id]) { selector.style.display = 'block' selector.innerHTML = metaData[id]; } } shippingInfo(currentVariantId); // When the variant is changed, get the id and call the function. :) document.addEventListener('variant:changed', function(event) { var variant = event.detail.variant; // Gives you access to the whole variant details var id = variant.id shippingInfo(id); }); </script>
What am i missing? what other things i have to change to relate to my theme? because the value doesn't change instantly...
Thank you!
User | Count |
---|---|
23 | |
21 | |
18 | |
17 | |
16 |