In my Shopify store on the product page I have a table with variant title, price and input quantity column. Could I added to the cart all input quantity for each variants of the product with AJAX ?
my table:
<form action="/cart/add" method="post" >
<tr>
{% for variant in product.variants %}
{% assign variant = product.selected_or_first_available_variant %}
<td>{{ variant.title }}</td>
<td>{{ variant.price | money }}</td>
<td>
<input name="quantity" inputmode="numeric" value="0">
</td>
{% endfor %}
</tr>
<input type="submit" value="Add to cart">
</form>
<script>
let addToCartForm = document.querySelector('form[action="/cart/add"]');
let formData = new FormData(addToCartForm);
fetch('/cart/add.js', {
method: 'POST',
body: formData
})
.then(response => {
return response.json();
})
.catch((error) => {
console.error('Error:', error);
});
</script>
And some Shopify documentation https://shopify.dev/api/ajax/reference/cart#post-cart-add-js
I'm trying added to cart all product variants for one call with AJAX and get:
Required parameter missing or invalid: items
Summary: Your form submission contains quantities but no products. You need to include the variant IDs as well.
In your for-loop, you have created quantity boxes for all of the variants in the product but are missing the variant IDs. When you post that data to /cart/add.js, Shopify has no way to know which products you're trying to put in the cart.
For adding multiple items in the cart at once, I would recommend taking a look at Shopify's documentation for the Cart API: https://shopify.dev/api/ajax/reference/cart#post-cart-add-js
To add multiple items to the cart, we need to submit a field called items as an array of objects specifying the IDs to add and optionally their quantities and any line-item properties we are attaching.
Here's a quick thought on how the resulting code might look:
<form class="custom-product-form" action="/cart/add" method="post">
<table>
{% for variant in product.variants %}
<tr>
<td>{{ variant.title }}</td>
<td>{{ variant.price | money }}</td>
<td class="item-submission">
<!-- Added hidden input for the variant ID -->
<input type="hidden" name="id" value="{{ variant.id }}"/>
<input name="quantity" inputmode="numeric" value="0">
</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Add to cart">
</form>
<script>
let addToCartForm = document.querySelector('.custom-product-form');
addToCartForm.addEventListener('submit', (evt) => {
evt.preventDefault();
// Update to create an object based on the multiple input rows
let items = [];
let rows = evt.currentTarget.querySelectorAll('.item-submission');
for(let i=0; i<rows.length; i++) {
// Get the variant ID and quantity for each row.
let itemData = rows[i];
let id = parseInt(itemData.querySelector('[name="id"]').value );
let qty = parseInt(itemData.querySelector('[name="quantity"]').value );
// We don't care about any rows with a quantity of 0
if(id && qty > 0){
items.push({ id: id, quantity: qty });
}
}
if(!items.length){
// Do something to tell the customer that there's nothing to add if all quantities were 0
return;
}
return fetch('/cart/add.js', {
method: 'POST',
body: JSON.stringify({ items: items }),
headers: { 'Content-type': 'application/json' },
credentials: 'include'
// Note: Including credentials sends the cart cookie, which is important to make sure that the items go into the shopper's cart and not into a void
})
.then(response => {
return response.json();
})
.catch((error) => {
console.error('Error:', error);
});
})
</script>