GlobalData.Settings.EnableMyProductMixselectItem when a product is clicked{
"items": [
{
"productId": "Product Id",
"productVariantId": "Variant Id",
"title": "Sample product title",
"sku": "Sample text",
"imageUrl": "https://example.com/media/sample.jpg",
"alias": "sample-product-alias",
"dimension1Name": "Sample text",
"dimension1Value": "Sample text",
"dimension2Name": "Sample text",
"dimension2Value": "Sample text",
"lastPurchasedPrice": 0,
"lastPurchasedQuantity": 1,
"lastPurchasedAtUtc": "2026-01-01T00:00:00.0000000+00:00",
"lastPurchasedTotal": 0,
"lastPurchasedTotalText": "Sample price text",
"currentPrice": 0,
"canOrder": false,
"minOrderQuantity": 1,
"maxOrderQuantity": 99,
"orderQuantityStep": 1,
"sellOutOfStock": true,
"stock": 0,
"quantityConstraints": {
"additive": {
"minimum": 1,
"maximum": 999999,
"step": 1,
"isValid": true
},
"absolute": {
"minimum": 1,
"maximum": 999999,
"step": 1,
"isValid": true
}
}
},
"..."
],
"currentPage": 1,
"totalPages": 2,
"totalCount": 23,
"pageSize": 20,
"name": "ProductMixList",
"view": "Default",
"section": "SectionA",
"settings": {
"id": "Component Id",
"section": "SectionA",
"type": "NoirProductMixList",
"name": "ProductMixList",
"configuredInContentApi": true,
"view": "Default",
"displayName": "",
"cssClass": ""
},
"translations": {
"myProductMix": "Sample text",
"noProducts": "Sample text",
"noProductsDescription": "Sample text",
"...": "..."
}
}settings.iditems[]currentPage, totalPages, totalCount, pageSizesettings.cssClassimageUrl (falls back to global no-image)dimension1Name, dimension1Value, dimension2Name, dimension2ValuequantityConstraints.*minOrderQuantity, maxOrderQuantity, orderQuantitySteptranslations.*Components/ProductMixList/Default.js exposes:<section
x-data='productmixlistdefault.productMixList(items, currentPage, totalPages, totalCount, pageSize, errorMessages)'
>errorMessages mapping.item._qty using getStartQuantity(item).fetch() from /api/product-mix/my-list.error = true and clears items.currentSort and refetches page 1.currentPage.Intl.NumberFormat(...) and window.__storeCurrency.false when the item can't be ordered or is out of stock (when sellOutOfStock === false).item._qty by orderQuantityStep up to maxOrderQuantity.item._qty by orderQuantityStep down to minOrderQuantity.[minOrderQuantity, maxOrderQuantity].servicesreusabledefault.addToCart(...).Alpine.store("toast") for error feedback.response.data.lineFailures[] exists, maps error types to translated messages via getLineFailureMessages(...).GET /api/product-mix/my-list?page=<n>&pageSize=<n>&orderBy=<sort>servicesreusabledefault.addToCart(productId, productVariantId, quantity, currentPrice, originalPrice)fetch (for list paging)prepareListProducts(...)sendGAEvent(...)toastservicesreusabledefault.addToCart(...) for add-to-cart.GlobalData.Settings.EnableMyProductMix.generatePages()), so they must stay in sync.{% for item in items %}<template x-for="..."> after any fetch/update (updateFlag).errorMessages JSON string in Liquid and passes it to initComponent(...).items is empty.quantityConstraints.additive.isValid == false.GlobalData.Settings.noImage (fallback to theme Assets/images/no-image.svg).