Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
We're moving the community! Starting July 7, the current community will be read-only for approx. 2 weeks. You can browse content, but posting will be temporarily unavailable. Learn more
Hey everyone,
I'm trying to add an upsell section on the product page in Dawn - one click should add 3 products. The liquid part is easy, but I'm stuck on the ajax.
I've seen a few tutorials on using Fetch like this one and was able to replicate that method, but it seems this isn't the method used in Dawn, and I wanted to understand how Dawn does it, and have a more seamless integration.
For the Add to Cart button, Dawn uses the FormData API and passes the product ID with a hidden input. Why can't I do this with multiple items also? E.g. -
<input type="hidden" name="items" value="{id:41643147788484,quantity:1},{id:41643131044036,quantity:1},{id:41572158046404,quantity:1}">
Another thing I tried is to pass the items list in product-form.js, under the line where formData is defined.
let items = [
{id:41643147788484,quantity:1},
{id:41643131044036,quantity:1},
{id:41572158046404,quantity:1}
]
const formData = new FormData(this.form);
formData.append('items', JSON.stringify(items))
Neither of these work, I'm getting a 400 error and the error message is "must be a collection of items: items"
Do I even need to use stringify in FormData API? My payload in chrome inspector seems ok.
Any advice? Thanks!
You have a create a JSON of all the products and then send it with fetch /add API.
You can contact me if you need help in setting up the upsell products.
Any luck with this? looks like multiple items cannot be sent with FormData 😕
Couldn't get it to work with FormData. Doesn't look like items works for it.
Did get it to work with json though.
Had to change the fetchConfig() to json and setup the appropriate body. Something important is to make sure you're using variant.ids and not product.ids or you'll get a 404 error on the request.
<input name="items[0][id]" value="123456789" >
<input name="items[0][quantity]" value="1" >
<input name="items[1][id]" value="987654321" >
<input name="items[1][quantity]" value="1" >
<input name="items[1][properties][first prop key]" value="first prop value">
<input name="items[1][properties][second prop key]" value="second prop value">
const items = [
{
"id": "123456789",
"quantity": 1
},
{
"id": "987654321",
"quantity": 1,
"properties": {
"first prop key": "First prop value",
"second prop key": "Second prop value"
}
},
]
const formData = new FormData();
buildFormData(formData, 'items', items);
function buildFormData(formData, key, data) {
if (data === Object(data) || Array.isArray(data)) {
for (const i in data) buildFormData(formData, `${key}[${i}]`, data[i]);
} else data && formData.append(key, data);
}
buildFormData function is self explanatory. It should output something like this when you log your formData Object, which you can then use in your body request:
console.log(Object.fromEntries(formData.entries()))
---
{
"items[0][id]": "123456789",
"items[0][quantity]": "1",
"items[1][id]": "987654321",
"items[1][quantity]": "1",
"items[1][properties][first prop key]": "First prop value",
"items[1][properties][second prop key]": "Second prop value"
}