I’m new to wix but have figured out how to integrate a custom ‘add to cart button’ in order to integrate the Wix Stores backend into a fully customized dynamic slug page. This is all in order to escape from the cookie cutter and non adjustable wix store layout. (Arg, I cant wait for Wix to let the layout be more adjustable so I can circumnavigate this problem)
I’m finding that the Add To Cart button works great for products that do not have product options. When a product does have a product option there is a an error code because the option has not been selected from a drop down (size, material etc) in order to complete the Add To Cart function.
Some of my products do not have options, some have size options, some have material options, some have combinations of options. I’d also like the user to input quantity into a text box and have all of this info feed into the Add to Cart button. Just as if this was the Wix Stores product page.
The code on my dynamic page reads as follows:
import wixData from ‘wix-data’ ;
import wixStores from ‘wix-stores’ ;
export function AddToCart_click(event) {
//Add your code for this event here:
}
Can anyone help me implement dynamic dropdowns (so that when an option(s) is available a drop down appears on the dynamic page, and input text box for inputting quantity?
My website/store is on pause until this problem is solved. Thanks!
Hi- did you get anywhere with this?
Or work around it?
I’m trying to do pretty much exactly the same and can’t find either a way to set up what I’d really like OR find a satisfactory work around.
If you could even get the ‘add to cart’ button to open the product page for products with options that would help.
I’ve even tried to use an ‘if’ statement to try to identify products with options so I can include extra instruction text for these in the repeater; sadly because the field is an ‘{} Option’ type this doesn’t seem to work either.
I never got an answer to this from wix. I did however simplify my product page as Wix prescribes within the constraints of the #productPage1 box. I then added additional product info into a dataset and was able to filter the dataset using the selected store product. I still had to show the fixed ‘store/product’ layout but in a simplified way and was able to play around with layout when showing other product info from my dataset. Not a perfect solution to my original question but was a work around. Funny enough my biz no longer necessarily needs a checkout function but I’ve kept the code in place in order to show my filtered dataset content and I’ve hidden and collapsed the ‘wix stores’ product box completely from view.
The code looks something like this:
import wixData from ‘wix-data’ ; import wixWindow from ‘wix-window’ ; import wixStores from ‘wix-stores’ ;
//connects product database to selected product from built in stores database// let product;
//the following two lines hides the #productpage1 box which is connected to the wix stores back-end. dont use the following two lines if you want to keep this box showing//
//the following two lines filters a dataset (in my case #dataset2) to the current product. In your dataset you need to reference each line/product to a product in the wix stores dataset for this to work This is 'refToStore (a reference in my dataset), product._id ( the product id of the current page)// async function filterDataset() { await $w( ‘#dataset2’ ).setFilter(wixData.filter().eq( ‘refToStore’ , product._id));
}
This explains my imperfect workaround. I wrote this code some time ago after weeks of trying many workarounds so my description of whats going on may not be perfect. This does not address the issues in my original question of needing reasonable flexibly with the stores/product layout in #productpage1 or how to connect option selections to the floating checkout or add to cart button. Anyways, hope this helps!!!
I never got an answer to this from wix. I did however simplify my product page as Wix prescribes within the constraints of the #productPage1 box. I then added additional product info into a dataset and was able to filter the dataset using the selected store product. I still had to show the fixed ‘store/product’ layout but in a simplified way and was able to play around with layout when showing other product info from my dataset. Not a perfect solution to my original question but was a work around. Funny enough my biz no longer necessarily needs a checkout function but I’ve kept the code in place in order to show my filtered dataset content and I’ve hidden and collapsed the ‘wix stores’ product box completely from view.
The code looks something like this:
import wixData from ‘wix-data’ ; import wixWindow from ‘wix-window’ ; import wixStores from ‘wix-stores’ ;
//connects product database to selected product from built in stores database// let product;
//the following two lines hides the #productpage1 box which is connected to the wix stores back-end. dont use the following two lines if you want to keep this box showing//
//the following two lines filters a dataset (in my case #dataset2) to the current product. In your dataset you need to reference each line/product to a product in the wix stores dataset for this to work This is 'refToStore (a reference in my dataset), product._id ( the product id of the current page)// async function filterDataset() { await $w( ‘#dataset2’ ).setFilter(wixData.filter().eq( ‘refToStore’ , product._id));
}
This explains my imperfect workaround. I wrote this code some time ago after weeks of trying many workarounds so my description of whats going on may not be perfect. This does not address the issues in my original question of needing reasonable flexibly with the stores/product layout in #productpage1 or how to connect option selections to the floating checkout or add to cart button. Anyways, hope this helps!!!
@bronsinablon Hey I followed your write up and it made things so much easier! I was wondering how did you connect the dropdowns or product option selections?
Hey! Thank you so much for sharing this code! I can´t make it work , it doesn´t filter acording to the product, it just shows the new dataset first product info.
import wix window and wixstore is grayed out, might that be the problem?
It´s very simple yet i can´t make it work!
Any help is really welcome! Still can´t believe wix provides such a limited product page design
@eugeniagarat Hi, I haven’t adjusted my code in quite a while but I may guess that either the wix code callouts/requirements has slightly changed or make sure all of your punctuation is technically correct with no misplaced spaces or characters to un-gray the 2nd and 3rd lines. . Otherwise appears you have followed precisely.
So, I created a custom product page that also check for product availability (more on that latter), the property you are looking for is the productOptions that you retrive from the .getCurrentItem() method of the dynamic dataset.
Something like this:
$w.onReady(() => {
let dataset = $w('#dataset') //Change this to your dateset element connected to the Stores/Products
dataset.onReady(async () => {
let currentProduct = dataset.getCurrentItem()
const { productOptions } = currentProduct //Destructuring of the productOptions
const option = 'size' //Change this to the option you named
const choices = productOptions[option].choices
const optionsForDropdown = createOptionsForDropdown(choices)
$w('#dropdown').options = optionsForDropdown //Change this dropdown to yours
})
})
//Function that returns the correct array for dropdown options
//It alsos returns if its inStock or not.
function createOptionsForDropdown(options) {
return options
.filter(option => option.inStock)
.map(option => {
return {
label: option.description,
value: option.description,
inStock: option.inStock,
}
})
}
Hey Bruno! This is amaziiiiing thanks a lot! It works beautifully.
Do you think it would be possible to grey out the options out of stock instead of not showing them in the dropdown? How would the code change?
@eugeniagarat I’m glad I could help you Euge. I don’t think you can edit the style inside the dropdown as of yet, just the whole dropdown style as one. But you could create a repeater with all the options you have and style it according to availability, let me know if that is an option for you.
@bwprado Hi Bruno! Yes! That would definetly be an option, actually I’ld like more that the sizes where showed as buttons rather than in a dropdown, but I’m afraid I’ld have to change my product page code as well as the code you shared, and I wouldn’t know how. It´s taken me months to finally get to make this code work, as I’m not a coder and I just tried and tried mashups of people examples and of wix tutorials. I’ll show you.
//Get current item, select size from dropdown and add to cart
$w.onReady(() => {
$w("#dynamicDataset").onReady(() => {
//gets current item
let itemObj = $w("#dynamicDataset").getCurrentItem();
//gets Id of current item
let productId = itemObj._id;
//Select
$w("#cartButton").onClick(() => {
//get selected size options
let Size = $w('#sizeSelector').value;
const products = [
{
productId,
"quantity": 1,
"options": {
"choices": {
"Size": Size
},
}
}
]
//add to cart function
cart.addProducts(products)
.then((updatedCart) => {
// Products added to cart
const cartId = updatedCart._id;
const cartLineItems = updatedCart.lineItems;
})
.then(() => {
console.log("Product added");
})
.catch((error) => {
console.log(error);
});
});
});
});
Do you think I could change this code so that I can replace the dropdown with a repeater/container and a button for each size?
When I finish the entire dynamic product page code with all the details I´m going to share it in the forum, I don´t understand why wix still didn´t make a tutorial or this or just make the product page more flexible, tons of people are asking for this.
@eugeniagarat It is a tough requirement cause it involves a lot of variables. For example, this code below creates the buttons inside the repeater with the available options for the selected product.
//This function prepares the Repeater for the incoming data, when $w('#rptColor').data = dataToRepeater is executed.
const prepareRptColor = () => {
$w('#rptColor').onItemReady(($item, itemData) => {
$item('#btnColor').style.backgroundColor = itemData.value //Assign the color to the button.
})
}
//Function that returns the correct array for repeater items
//It alsos returns only the options that are inStock.
const createRepeaterOptions = (options) => {
return options.filter(option => option.inStock).map((option, index) => {
return {
_id: index.toString(),
value: option.value,
description: option.description
}
})
}
$w.onReady(() => {
//You call it once on page load to prepeare the repeater
prepareRptColor()
let dataset = $w('#dataset') //Change this to your dateset element connected to the Stores/Products
dataset.onReady(async () => {
let currentProduct = dataset.getCurrentItem()
const { productOptions } = currentProduct //Destructuring of the productOptions property from the currentProduct
const option = 'Color' //Change this to the option you named in the Product Dashboard, remember it is case sensitive and should be a string
const { choices } = productOptions[option] //Destructuring of the choices option from the productOptions['Color']
const dataToRepeater = createRepeaterOptions(choices)
$w('#rptColor').data = dataToRepeater
})
})
But after that you will have to treat the button selection with a different code that will have to run and check availability for each size and selected color combination.
The code would be something like this:
iimport wixStoresBackend from 'wix-stores-backend'
//This function creates an array of objects with the choices combinations of all sizes and available colors.
const createOptionsArray = product => {
const { productOptions } = product
const keys = Object.keys(productOptions)
const choices = keys.map(key =>
productOptions[key].choices.map(choice => {
return {
[key]: choice.description,
}
})
)
if (choices.length < 2) return choices.flat()
const [a, b] = choices
const newChoices = b
.map(s =>
a.map(c => {
return {
[keys[0]]: c[keys[0]],
[keys[1]]: s[keys[1]],
}
})
)
.flat()
return newChoices
}
//This function runs an availability check for each combination object and return every combination that is available for purchase
export const getCurrentProductsAvailability = async currentProduct => {
const allProductOptions = createOptionsArray(currentProduct)
const arrayOfPromises = allProductOptions.map(obj =>
wixStoresBackend.getProductOptionsAvailability(currentProduct._id, obj)
)
const result = await Promise.all(arrayOfPromises)
let choicesInStock = allProductOptions.map((item, index) => ({
...item,
inStock: result[index].availableForPurchase,
}))
return choicesInStock.filter(obj => obj.inStock === true)
}
This has to run every time you change the selected color.
You will also have to treat the button with the unavailable size.
It is a quite complex code to implement.
I have one ready and working that I developed for a client, but it is not very easy to understand.
@bwprado Bruno, thank you so much for taking the time to share this with me! I believe it is out of my reach so will probably stick to the dropdown code, but definetly won’t quit without give it a few tries.
How do you have the options stored in your collection? I’m having trouble with populating a dropdown that is connected to a collection that I have created. Do I use the object, array or tags field? I’ve tried array and object and I keep getting an error.