Home
Wiki
Home
Wiki
  1. 2. Components
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 6. FAQ
    • 1. Structure
      • _Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • _Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Quote
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • _Overview
      • Addresses
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • BillingRetail
      • Company
      • General
      • Login
      • LoginModal
      • MonthlyTransactions
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Quotes
      • Register
      • Services
      • Shipping
      • ShoppingLists
      • ShoppingListsButton
      • ShoppingListsNavbar
      • Toast
      • Transactions
      • Users
      • VariantContent
      • WishlistButton
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • _Overview
        • theme.js
      • Css - Scss
        • _Overview
        • ThemeClasses
    • 5. SDK
      • _Overview
      • LiquidGlobals
      • ServicesSDK
  1. 2. Components

Cart

Purpose#

The Cart component renders the cart page UI, including:
Cart items list (with quantity editing, removal, undo removal)
Optional “Quick add product” search (if enabled by global settings)
Cart validation errors (e.g. product not found / quantity rules / stock issues)
Order summary section
Clear cart flow with confirmation modal
Optional wishlist integration (move to wishlist, toggle, etc.)
Optional matrix view for variants (when variantsDisplayType = "Matrix")

Inputs (model contract)#

Model shape (storefront example)#

{
  "errorCode": null,
  "name": "Cart",
  "view": "Default",
  "section": "SectionA",
  "settings": {
    "variantsDisplayType": "Simple",
    "id": "Component Id",
    "section": "SectionA",
    "type": "NoirCart",
    "name": "Cart",
    "configuredInContentApi": true,
    "view": "Default",
    "displayName": "Sample display name",
    "cssClass": ""
  },
  "translations": {
    "cart": "Sample translation",
    "noProductsInTheCart": "Sample translation",
    "goToCheckout": "Sample translation",
    "...": "..."
  }
}

Required fields#

settings.id
Used for wrapper id: comp-{{ id }}

Optional fields#

settings.cssClass
Applied to wrapper only when non-empty and not (UNDEFINED).
settings.variantsDisplayType
Controls variant display mode:
Simple (default)
Matrix (enables grouping behavior in JS)
errorCode
When present, shows a checkout-related error banner near the top of the cart.

JavaScript#

Global object#

The Cart component exposes a global object:
It’s initialized from Liquid via Alpine:
x-data="cartdefault.initComponent(variantMatrixView, updateProductCartErrorMessage, updateProductQuantityErrorMessage)"
initComponent(...) returns a large Alpine component object that:
reads live cart state from Alpine.store("cart")
maintains local UI state (loading flags, ghost items, grouped items)
performs async cart operations through servicesreusabledefault
drives sticky layout behavior and quick add behavior

initComponent#

Factory that returns the Alpine state + handlers for the Cart UI.

init#

Runs on Alpine mount. It refreshes items, wires resize/scroll listeners for sticky behavior, and watches Alpine.store("cart").items to keep UI in sync.

groupedCartItems#

Groups cart lines by productId when matrix view is enabled.

updateHeaderHeight#

Stores the current header height in this.headerHeight so sticky elements can be positioned correctly.

updateStickyElementTop#

Applies the stored header height as the top offset on .cart-aside.

refreshItems#

Refreshes cart UI state by merging live cart-store items with “ghost items” (undo), and updates this.allItems (grouped in matrix mode).

sendSelectEvent#

Sends GA selectItem for a clicked product.

clearCart#

Clears the cart via servicesreusabledefault.clearCart() and shows a toast on failure.

handleClearCartModal#

Opens the global confirmation modal and clears the cart when the user confirms.

addProductInWishlist#

Moves an item to wishlist (via Alpine.store("wishlist")) and then removes it from cart (single item or whole group in matrix mode).

removeProduct#

Removes an entire grouped product (all variants) in matrix mode.

removeItem#

Removes an item from cart via servicesreusabledefault.removeFromCart(...) and optionally creates a “ghost item” so the user can undo.

addProduct#

Adds an item back to cart (used for undo) via servicesreusabledefault.addToCart(...) and refreshes UI state.

debounceUpdate#

Debounces updateProductCart(...) per item and cancels any pending request for the same line.
Debouncing is important because notes/quantity edits can generate many updates quickly.

debounceUpdateProduct#

Same strategy as debounceUpdate, but for quantity updates:
schedules updateQuantity(..., checkQuantity, false) after delay
Uses debounceMap[product.id] and cancelTokenMap[product.id].
Different methods use item.id vs product.id as keys. Make sure the passed objects actually have the expected id field, or debounce/cancel won’t work properly.

updateProductCart#

Persists cart item changes (notes/quantity) by:
1.
If useDebounce is true → delegates to debounceUpdate(item) and returns.
2.
Clears toasts.
3.
Cancels any previous in-flight request for the same item (cancelTokenMap[item.id]).
4.
Creates a new axios cancel token.
5.
Reads current cartData from localStorage.
6.
Finds the matching cart item in cartData.cartItems by id and updates its notes and quantity.
7.
Calls:
servicesreusabledefault.updateProductCart(cartData, cancelToken)
8.
On failure: shows toast using updateProductCartErrorMessage.
9.
Clears cancel token entry and loading flag.
Critical dependency: localStorage cartData must exist and match the updated store.
If cartData is missing, this method currently returns early without resetting isLoading (it sets this.isLoading = true before reading). If you see a stuck loader, this is a reason to add a safe finally/cleanup.
If you ever add more editable fields, update the localStorage mutation logic accordingly.

increaseQuantity#

Computes step/min/max from:
product.quantityConstraints.absolute.step (default 1)
product.quantityConstraints.absolute.maximum (default Infinity)
uses minimum as fallback base
Increments quantity by step, clamps to max.
Sets product.quantity = newQty and calls:
this.updateProductCart(product, true) (debounced)
This does not call server-side quantity validation directly; it relies on cart update + optional validation flow elsewhere.
If you need strict stock validation before applying changes, use updateQuantity(..., checkQuantity=true).

decreaseQuantity#

Decrements quantity by step, clamps to min.
Updates product.quantity and calls updateProductCart(product, true).
Same as increase: it’s fast UI-side, then persisted via debounced update.

updateQuantity#

Two-mode quantity update:
A) checkQuantity === true (server-validated quantity)
If useDebounce is true:
debounces via debounceUpdateProduct(...) and returns
Cancels previous request for product.id
Calls:
servicesreusabledefault.updateProductQuantity({ productId, productVariantId, requestedQuantity }, cancelToken)
On failure:
shows toast using updateProductQuantityErrorMessage
returns
On success:
sets this.quantity = response.data?.absoluteQuantity.value
sets product.quantity accordingly
calls this.updateProductCart(product, true) (debounced persistence)
B) checkQuantity === false (no server validation)
Sets this.quantity = newQuantity
Updates product.quantity
Calls updateProductCart(product, true)
If you have strict quantity rules (min/max/step, stock), prefer checkQuantity = true.
this.quantity is used as a shared field; in concurrent updates it can be overwritten. If that starts causing UI bugs, move quantity state to per-item keyed storage.

handleCheckout#

If userAuthenticated is true:
redirects to /checkout
Otherwise:
sets Alpine.store("loginModal").goToCheckoutPage = true
opens login modal: Alpine.store("loginModal").open(true)
userAuthenticated comes from a global injected variable (layout).
Ensure it’s available on the cart page; otherwise this will throw.

itemInvalid#

Checks this.cartValidation.lines (if available) and returns whether the given cart line id is part of a failed validation line.
Logic:
finds a validation line where line.lineIds contains itemId
returns !line.isSuccess when found, otherwise false
This assumes cartValidation uses lineIds that match cart item id. If backend changes ids, invalid highlighting will break.

clearItems#

Removes multiple items that belong to a validation error group:
Sets this.errorRemoving[errorType] = true (per-error-type loading flag)
Filters cart store items whose id is in lineIds
For each item:
finds its index in this.allItems
calls removeItem(productVariantId, idx, clearItemErrorMessage, 0, false) (no undo)
refreshes items
Re-fetches validation:
const response = await servicesreusabledefault.getCartData()
this.cartValidation = this.parseCartValidation(response.data)
Clears loading flag.
This removes items sequentially, which is safer and yields consistent state.
Pass showUndo = false intentionally here: validation cleanup should be definitive.

getTotalQuantity#

In matrix mode, sums quantity across non-deleted variants:
ignores variants where isDeleted === true
Quantity defaults to 0 when missing.

getTotalPrice#

Sums subTotalPrice across non-deleted variants.
Returns a string with 2 decimals via .toFixed(2).
This returns a string. If you later need numeric arithmetic on the result, parse it.

quickAddProductComponent#

Returns an Alpine sub-component used by the “Quick add to cart” feature.
It provides local state:
showSearchResult, searchLoading, searchText
resultProducts
timerId (for debounce)
maxSearchResult
isAdding
and methods:
search(searchSize = 5)
triggerVoiceSearch()
isOrderable(product)
handleAddItem(product, addToCartErrorMessage, showPopUp = true)
This is a nested Alpine object pattern. It relies on being evaluated inside the parent component scope so it can call this.updateQuantity(...) and access stores/services.

search#
Debounces product search by 400ms.
If searchText is empty:
hides results and clears list
Otherwise:
shows results area, sets loading
after delay, builds criteria:
{ page: 1, pageSize: searchSize + 1, sort: "-SortDate", search: this.searchText }
calls:
servicesreusabledefault.findProductsByCriteriaExtended(criteria)
stores results into resultProducts
clears loading in finally
Updates maxSearchResult to at least 5.
pageSize: searchSize + 1 is typically used to detect “has more results” UI. If you don’t use it, you can simplify.
Consider trimming searchText to avoid queries for whitespace.

triggerVoiceSearch#
Uses Web Speech API (SpeechRecognition / webkitSpeechRecognition) to capture voice input.
If unsupported:
alerts the user
Otherwise:
starts recognition (lang = "en-US")
on result:
sets searchText to transcript
opens results area
Language is hardcoded to "en-US". If your storefront locale is Greek, you probably want "el-GR" or dynamic locale-based selection.
alert(...) is a blunt UX. If you want consistency, replace with Alpine.store("toast") error message.

isOrderable#
Returns true if:
single-variant product has quantityConstraints.absolute.isValid, OR
product is multi-variant
Otherwise returns false.
It references this.isSingleVariant and this.isMultiVariant, which must be provided by the template scope (or computed elsewhere).
If they’re missing, this will always fall back to falsey behavior. Make sure those flags exist in the quick-add template.

handleAddItem#
Two paths:
A) Single-variant products
Clears toasts, sets isAdding = true
Picks the first variant:
product.productVariants[0]
Calls:
servicesreusabledefault.addToCart(product.id, variant.id, variant.minimumQty, variant.finalPrice, variant.originalPrice, showPopUp)
On failure:
shows toast and stops
On success:
finds added cart item from response
calls this.updateQuantity(minimum, addedProduct, addedProduct.productVariantId)
Clears isAdding.
B) Multi-variant products
Opens product modal:
Alpine.store("productModal").open(product, "cart")
Quick add assumes variant[0] exists for single-variant items. Add a guard if backend can return empty variants.
For multi-variant items, the modal flow depends on the productModal store existing globally.

Global Alpine stores (used by Cart)#

The Cart component is store-driven and depends heavily on shared Alpine stores that live in Assets/js/theme.js.

Alpine.store("cart")#

(cart state)
This is the single source of truth for cart totals and items across the theme.
Defined in Assets/js/theme.js as Alpine.store("cart", ...).
Key fields:
items (array)
Current cart items.
netValueText, vatValueText, finalPriceText
Totals displayed in the UI.
count (getter)
Total quantity across all items.
Key behaviors:
loadFromStorage()
Loads cart data from localStorage.cartData.
update(cartData, addedProductsArray = [], showPopUp = false)
Updates store state and persists it back into local storage.
Can optionally show a popup with added products.
Also listens for storage events on cartData so multiple tabs stay in sync.

Alpine.store("toast")#

(user feedback)
Used for showing error/success feedback.
Common pattern:
Alpine.store("toast").removeAll();
Alpine.store("toast").add(message, "ic-warning", "error");

Alpine.store("modal")#

(confirmation dialogs)
Used to show confirmation dialogs (e.g. clear cart confirmation).
Cart opens a modal with buttons/actions, then invokes clearCart(...) if confirmed.

Alpine.store("wishlist")#

(optional)
Cart interacts with wishlist when wishlist is enabled by global settings (e.g. “move to wishlist” / toggle flows).

Alpine.store("loginModal")#

(checkout gating)
When the user is not authenticated, checkout is gated through the login modal:
sets Alpine.store("loginModal").goToCheckoutPage = true
opens the login modal so the user can continue to checkout after login

Dependencies#

Alpine.js
Alpine stores: cart, toast, modal, and optionally wishlist, loginModal
Services layer (servicesreusabledefault) for cart API calls:
clear/remove/update/quantity validation, etc.
Additional tokens used by the Cart implementation:
$store.productModal (used to open variant selection from quick add)
$store.wishlist (used when moving cart lines to wishlist)
servicesreusabledefault.getCartData() (used to refresh cart state)

Notes#

Cart UI is driven by Alpine.store("cart").items (loaded from local storage) and then updated by API calls and store updates.
In matrix mode, items are grouped by productId and rendered/managed as groups with variants inside.
“Ghost items” are used to support an undo-like UX after removal (items stay visible temporarily as deleted).
Quick add search and wishlist integration are feature-flagged by global settings; they may not appear in all stores.

Extras#

Template behavior (Liquid + Alpine)#

The component initializes via:
x-data="cartdefault.initComponent(variantMatrixView, updateProductCartErrorMessage, updateProductQuantityErrorMessage)"

Cart visibility#

The main cart layout is shown when:
Alpine.store('cart').items.length > 0 OR
ghostItems.length > 0 (items recently removed but still visible for undo)

Quick add product (optional)#

Quick add is shown only when a global setting is enabled:
GlobalData.Settings.EnableQuickAddToCart
This enables:
search input
results dropdown
add-to-cart buttons for results

Cart validation errors#

On first load (when there are items), the component calls cart validation:
servicesreusabledefault.getCartData()
If validation returns lines with errors, the UI shows grouped error blocks and enables “remove items” actions per error type.

Clear cart modal#

The template builds a JSON-like translation payload for the confirmation modal, then the JS uses the global modal store to open it.
Modified at 2026-05-12 06:54:33
Previous
Breadcrumb
Next
CategoriesList
Built with