Using CartJS with Multiple Variant Dropdowns - shopify

I'm stuck getting CartJS to work with multiple variant dropdowns in Shopify. It's currently giving a 400 (Bad Request) whenever I try to add a product to cart. Which I'm guessing is because my Variant is empty. My current code is:
{% for product_option in product.options_with_values %}
<label>
{{ product_option.name }}
<select>
{% for value in product_option.values %}
<option {% if product_option.selected_value == value %}selected{% endif %}>
{{ value }}
</option>
{% endfor %}
</select>
</label>
{% endfor %}
And the option_selector code.
<script>
var selectCallback = function(variant, selector) {
timber.productPage({
money_format: "{{ shop.money_format }}",
variant: variant,
selector: selector
});
};
(function($) {
new Shopify.OptionSelectors('productSelect', {
product: {{ product | json }},
onVariantSelected: selectCallback,
enableHistoryState: true
});
// Add label if only one product option and it isn't 'Title'. Could be 'Size'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label for="productSelect-option-0">{{ product.options.first | escape }}</label>');
{% endif %}
// Hide selectors if we only have 1 variant and its title contains 'Default'.
{% if product.variants.size == 1 and product.variants.first.title contains 'Default' %}
$('.selector-wrapper').hide();
{% endif %}
});
</script>

Linked options might be the way to go.
It matches the values from the selectors(dropdowns) in order to get the right variant.
https://help.shopify.com/en/themes/customization/products/variants/link-product-options-in-menus

Related

Display Items in Collection that Do Not Exist In Shopping Cart Shopify

I'm trying to iterate over items in the shopping cart and generate an upsell div with products NOT in the cart. Below is the code I have so far, but I run into issues when adding two items to cart running the loop twice generating the html twice. Any ideas on how to resolve it? I'm stumped.
{% for item in cart.items %} // iterates over items in cart
{% if item.product.id == 4456879040188 %} // checks if product id matches in item in cart
<div class="upsell-pop" style="text-align:center; width: 100%;">
<h4>Frequently bought together</h4>
{% for prod in collections.upsell.products %} // iterates products in collection upsell
{% unless prod.handle contains "product-name" %} // shows only prods that do not contain url handle
<div>
<span class="upsell-title">{{ prod.title }}</span>
<span class="upsell-price">{{ prod.metafields["meta"]["promo"] }} {{ prod.price | money }}</span>
<img src="{{ prod.featured_image | img_url: '200x' }}" />
<a class="btn-product" href="{{prod.url}}">View Product</a>
</div>
{% endunless %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
Another thought is to somehow check to see if product is NOT in cart items inside to replace the existing "unless" statement, but not sure how to code it.
{% unless cart.items exist then %} // I know this is not correct syntax
<div>
<span class="upsell-title">{{ prod.title }}</span>
<span class="upsell-price">{{ prod.metafields["meta"]["promo"] }} {{ prod.price | money }}</span>
<img src="{{ prod.featured_image | img_url: '200x' }}" />
<a class="btn-product" href="{{prod.url}}">View Product</a>
</div>
{% endunless %}
On my mind, there are two steps here.
First, capture your cart content to get string to compare to when you loop through your upsell collection. This could be something like that:
{%- capture cart_items -%}
{% for item in cart.items %}
{{ item.product.handle }}{% unless forloop.last %} , {% endunless %}
{% endfor %}
{%- endcapture -%}
Then loop through your collection while checking your string does not contain the handle of the current product at each iteration:
{% for product in collections['upsell'].products %}
{% unless cart_items contains product.handle %}
{{ product.title }}
{% endunless %}
{% endfor %}
Remarks:
Snippet 1 => In line_item (here called item because it's shorter to write) object you may access product object attributes: item.product.product_attr_needed
Snippet 2 => To access directly a collection object using its handle you must use collections + square brackets containing collection handle + attribute. Here 'upsell' is the handle of your upsell collection.
Not tested but this should work.
HTH

How to pass data from Vue component to a twig function

Vue.component('my-component', {
template: '#my-component',
data: function () {
return {
items: []
}
}
});
{% macro page() %}
<script type="text/x-template" id="my-component">
<div>
{% pagination(items) %} //<===== How to pass variable items to pagination
</div>
</script>
{% endmacro %}
{% macro pagination(items) %}
<select name="p">
{% for key, value in items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
{% endmacro %}
My question, how can I pass the variable items from my component to a twig function pagination. I've spend few hours on this, but it still doesn't seems to work. It should be a correct way to pass the variable from component to a twig function.

How to access Shopify API in liquid or javascript variables in liquid?

From what I can find, it seems that this may be impossible. There must be someway to do this though. All I want to do is get some information from the API, and pass it to a liquid variable. Maybe there's another way.
Since liquid renders server side you can't pass javascript variables into the template engine. However you can embed liquid template code in javascript functions. There's a post on the shopify forums with some example code that may help: Pass variable from Java script to liquid?
for example:
$(function() {
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });
// Add label if only one product option and it isn't 'Title'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
{% endif %}
// Auto-select first available variant on page load.
{% assign found_one_in_stock = false %}
{% for variant in product.variants %}
{% if variant.available and found_one_in_stock == false %}
{% assign found_one_in_stock = true %}
{% for option in product.options %}
$('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
{% endfor %}
{% endif %}
{% endfor %}
});

Change Color title for all products

I'm trying to change the variant title "color" to "flavor". I've tried to change it in the code but not working. I have thousands of products and to change Color for each one will be way to much work. The code where the title color displays is listed below. Is this even possible?
<select name="id" id="productSelect" class="product-variants">
{% for variant in product.variants %}
{% if variant.available %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{ 'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
This can be done using the Shopify API.
see this answer for a fully worked node.js script. It creates a product. for updating the product you'd have to get all your products that have color as a variant name and run something like:
var options = {
host: 'mydomain.myshopify.com',
port: 443,
path: '/admin/products/1925263361.json', // per product
method: 'PUT',
headers: headers
};
...
var product = {
product:{
id:'1925263361',
options : [ // just update the variant titles; no other fields
{name : "Bob"}, //was First
{name : "Carol"}, // was Second
{name : "Third"}
]
}
};

Variant Id in search.json.liquid file in shopify

I need to pass variant id in search.json file in shopify as I am using to add products through variant id in search.autocomplete.liquid file. I have checked they are using variables to call the product 'title, url & thumbnail' in loop as mentioned in the below code. Is there any way to create variable for 'variant id'.
{% layout none %}
{% assign product_cunt = search.results_count %}
{% paginate search.results by product_cunt %}
{% capture results %}
{% for item in search.results %}
{% assign product = item %}
{ "title" : {{ product.title | json }},
"url" : {{ product.url | within: product.collections.last | json }},
"thumbnail": {{ product.featured_image.src | product_img_url: 'thumb' | json }},
"variant" : (I need to add variant id variable here)
}
{% unless forloop.last %},
{% endunless %}
{% endfor %}
{% endcapture %}
{% endpaginate %}
{ "results_count": {{ search.results_count }},
"results": [{{ results }}]
}
Thanks very much for looking into this.
I have found the solution of it mentioned below If anybody has same concern.
just need to get the first available variant's ID, you should be able to use
product.selected_or_first_available_variant.id
there to get the ID of the first available variant for that product.