Is it possible to have separate variant option fields on a front end add to cart form?
For example… have a separate select field for Color and a separate select field for Size?
Craft CMS Stack Exchange is a question and answer site for administrators, end users, developers and designers for Craft CMS. It only takes a minute to sign up.
Sign up to join this communityIs it possible to have separate variant option fields on a front end add to cart form?
For example… have a separate select field for Color and a separate select field for Size?
It's definitely possible and doesn't really need any custom back end code to be done in general.
Ultimately all add to cart options in Commerce are just a simple case of POSTing the variant id and the quantity of that variant.
Generally I would do this all in twig & a bit of JS.
E.g. In twig I wouldt loop through all variants (checking for stock as I go) and build up a JSON array of all the combinations of colour & size, and their availability due to stock. I'd then 'pass this into' my form as a data-variants
attribute.
Actually building the selects is slightly trickier because one will depend on the other but basically you'd probably want some JS that listens to your selects and looks at your passed in array to see if a particular size and colour combination was in stock - if a chosen combination is not, some sort of visual indication and disable the add to cart button, otherwise if it is in stock the form just posts the variant id and the qty and away you go.
Updated with some sample code:
Here's some untested/pseudo code that should get you on the right track:
so the important thing to understand is that the descriptive data of a variant is really a completely separate concern to the sku of the variant - which in turn is not actually all that relevant to commerce - the variant id
is really all that matters in the end in terms of addToCart. For specifiying the variant data you can do it any way you like really but in this case if it's just say 3 colours and 3 sizes, then a simple approach would be a dropdown for each of those, with handles colour
and size
say.
You then just make the 9 variants, choose the colour and size for each, and enter the sku for each.
Then, you want to make the JSON for use in the JS. (It's hard for me to see how you'd have a good UX without JS here, to be honest).
Here the |jsonencode
filter is handy. Something along the lines of:
{% set stockArray = [] %}
{% for variant in product.variants %}
{% set stockArray = stockArray|merge([{variantId:variant.id,
variantColourAndSize :variant.colour ~ "-" ~ variant.size,
variantIsUnlimited:variant.unlimitedStock,
variantStock:variant.stock,
}]) %}
{% endfor %}
Then you output your form and pass this consolidated data in to it so it's accessible in the JS:
<form id="OrderForm"
data-stockarray="{{ stockArray|json_encode() }}"
data-action="/actions/multiAdd/multiAdd"
data-redirect="/cart"
etc
>
<selects here>
The rest is really just JS operating on that json data - this is thoroughly pseudo code since it's Friday night :) - but should be enough to get the idea:
var $form = document.getElementById('OrderForm');
var stockArray = $form.dataset.stockarray;
// Listen to your selects and look up in this array whether the matching colour/size variant is in stock/has unlimited stock
var variantKey = $select1.val() + "-" + $select2.val();
if(stockArray[variantKey].variantIsUnlimited || stockArray[variantKey].variantStock > 0 ){
// Enable/Disable your add to cart button accordingly
$addToCartButton.show();
}
else {
$addToCartButton.hide();
}