Home
Wiki
Home
Wiki
  1. 3. Reusables
  • 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
    • 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
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • Overview
      • Addresses
      • BillingRetail
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • Company
      • General
      • Login
      • LoginModal
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ShoppingListsButton
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Register
      • Shipping
      • ShoppingLists
      • ShoppingListsNavbar
      • Toast
      • Users
      • VariantContent
      • WishlistButton
      • Services
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • Overview
        • theme.js
      • Css / Scss
        • Overview
        • ThemeClasses
    • 5. SDK
      • Overview
      • LiquidGlobals
      • ServicesSDK
  1. 3. Reusables

ProductListItem

Purpose#

The ProductListItem reusable renders a product card in “list view” (row layout), typically used in catalog/search pages when the user switches from Grid to List. It supports:
product image, category, title, brand
product labels (ico tags)
quick actions (comparison, wishlist, shopping lists)
variant dimension selection (including mobile color preview)
add-to-cart/quantity interaction via JS
GA select-item tracking

Where it's rendered#

This reusable is rendered primarily from Components/FilterList/Default.liquid when view == 'List':
{% render 'Reusables\\ProductListItem\\Default',
  product: product,
  modelId: id,
  colorExists: colorExists,
  listName: listName,
  position: forloop.index0
%}

Inputs (Liquid render parameters)#

Named parameters:
product
The product object shown in the list item.
modelId
Used to build a unique key (modelId-product.id) for DOM scoping.
colorExists
Used to keep layout consistent in lists (adds a placeholder when some products have color variants and others do not).
listName
Used for GA select-item events.
position
Used for GA select-item events.

Template behavior (Liquid + Alpine)#

High-level rendering:
Builds productImage from product.mediaItems[0] when available.
Initializes Alpine via:
x-data='productlistitemreusabledefault.initComponent({{ product | serialize | escape }}, "{{ Reusables.ProductListItem.Translations.AddToCartErrorMessage }}", "{{ Reusables.ProductListItem.Translations.UpdateProductQuantityErrorMessage }}")'
Image + navigation:
Links to /product/{{ product.alias }} and sends GA select-item via sendSelectEvent(...).
Has keyboard handlers for Enter/Space.
Labels:
If product.icoTags exists, it renders label badges (desktop and mobile layouts).
Quick actions:
Comparison: Reusables/ProductComparisonButton
Wishlist: Reusables/WishlistButton
Shopping lists: Reusables/ShoppingListsButton
Each is gated by feature flags:
GlobalData.Settings.ShowProductComparison
GlobalData.Settings.EnableWishlist
GlobalData.Settings.EnableShoppingLists
Brand:
If product.brand.* exists it renders a brand badge (image when available, otherwise text).
Category + title:
Uses product.categoryName / product.categoryLink (when present).
Uses product.title and links to /product/{{ product.alias }}.
Color preview (mobile only):
When colorExists is true and the product has a Color dimension with multiple variants, it shows up to 3 color dots and a “+N” indicator.
If some products don’t have a color dimension, it renders a placeholder block to keep rows aligned.
Image fallback:
If there is no image link it falls back to GlobalData.Settings.noImage.link or /Assets/images/no-image.svg.

Data contract (JS runtime)#

Model shape (storefront example)#

Example (from a real product list response) keeping only the fields that matter to this reusable:
{
  "id": "Product Id",
  "title": "Sample title",
  "alias": "sample",
  "categoryName": "Sample text",
  "categoryLink": "/category/sample",
  "mediaItems": [
    {
      "id": "Media Id",
      "link": "https://example.com/sample",
      "position": 0,
      "alt": "Sample text",
      "mediaType": "Image"
    },
    ...
  ],
  "icoTags": [
    {
      "id": "Tag Id",
      "name": "Sample text",
      "backgroundColor": "Sample text",
      "textColor": "Sample text",
      "icon": { "link": "https://example.com/sample" }
    },
    ...
  ],
  "brand": {
    "name": "Sample text",
    "link": "/brand/sample",
    "image": { "link": "https://example.com/sample", "alt": "Sample text" }
  },
  "dimension1": {
    "type": "Color",
    "name": "Sample text",
    "items": [ { "id": "Dim Item Id", "value": "Sample text", "textColor": "Sample text" }, ... ]
  },
  "dimension2": {
    "type": "Size",
    "name": "Sample text",
    "items": [ { "id": "Dim Item Id", "value": "Sample text" }, ... ]
  },
  "productVariants": [
    {
      "id": "Variant Id",
      "dimension1ItemId": "Dim Item Id",
      "dimension2ItemId": "Dim Item Id",
      "finalPrice": 25,
      "finalPriceText": "25,00 €",
      "originalPrice": 35,
      "originalPriceText": "35,00 €",
      "canOrder": true,
      "sellOutOfStock": false,
      "quantity": 2,
      "minOrderQuantity": 1,
      "orderQuantityStep": 1
    },
    ...
  ],
  "startPrice": 25,
  "startPriceText": "25,00 €",
  "hasPriceRange": false,
  "inWishlist": false
}

Fields consumed directly by Liquid#

The Liquid template reads (direct reads visible in Default.liquid):
product.id, product.title, product.alias
product.categoryName, product.categoryLink
product.mediaItems[0].link, product.mediaItems[0].alt
product.icoTags[] (label rendering)
product.brand.name, product.brand.link, product.brand.image.link, product.brand.image.alt
product.productVariants (size and conditional blocks)
product.dimension1, product.dimension2 and nested .type, .name, .items[] (mobile color dots)

JavaScript#

Global object#

Global object: productlistitemreusabledefault
Liquid wiring:
x-data="productlistitemreusabledefault.initComponent(product, addToCartErrorMessage, updateProductQuantityErrorMessage)"

initSwiper(refs)#

What it does
Creates a Swiper instance for dimension pickers (when list item renders variant pickers that use Swiper).

initComponent(product, addToCartErrorMessage, updateProductQuantityErrorMessage, isProductSection = false)#

What it does
Returns the Alpine component instance for the list item.
Initializes selection state for dimensions/variants.
Handles add-to-cart and server-side quantity validation.
Advice
This reusable serializes the full product object into the DOM ({{ product | serialize | escape }}). Keep the product payload reasonably sized.

init() (returned by initComponent)#

What it does
Detects which dimension is Color and sets colorDimKey / otherDimKey.
Auto-selects dimension items when a dimension has exactly one option.
If the product has no dimensions, preselects the first variant and calls updateSelectedVariant().
Wires click handling via handleClickEvents().
Updates isMobile on resize.
When isProductSection is true, enables sticky/scroll helpers.

sendSelectEvent(product, listName, position)#

What it does
Sends GA selectItem for the clicked product.

sendSelectEventAndRedirect(product, listName, position)#

What it does
Sends GA selectItem and then navigates to /product/${product.alias}.

handleClickEvents()#

What it does
Handles middle-click / Ctrl-click to open the product in a new tab while sending GA tracking.

setSelectedColor(id, label) / setSelectedOther(id, label) / setDimension(key, id, label)#

What they do
Update the selected dimension ids/labels and call updateSelectedVariant().

updateSelectedVariant()#

What it does
Finds the variant matching the selected dimension ids.
Sets selectedVariant and selectedVariantIndex.
Calls updateQuantity(...) using quantity constraints.
Calls getActiveImage(...) (used in product section contexts).

selectedVariant / isSingleVariant / isMultiVariant / shouldShowAddToCartButton / showMobileModalButton (getters)#

What they do
Provide derived state for template decisions (selected variant presence, mobile behavior).

handleAddToCart(groupVariant = null)#

What it does
Adds the selected product variant to cart via servicesreusabledefault.addToCart(...).
Supports an optional groupVariant to add a specific variant (used by some UI modes).
Uses $store.toast to show errors.

hasMultipleVariants / allDimensionsSelected / displayStartPrice / displayFinalPrice / displayOriginalPrice (getters)#

What they do
Provide derived UI state for pricing and selection completeness.

isOtherOptionOrderable(otherId) / isSingleOptionOrderable(dimId, isDim1) / canAddToCart()#

What they do
Determine orderability by checking variant quantityConstraints.additive.isValid among matching variants.

variantOrDefault(path, displayNullLine = false)#

What it does
Reads a nested value from the selected variant first, then falls back to the product.

getDynamicLabelClass(el)#

What it does
Computes a CSS class for availability labels based on stockAvailability.label.

swiperInitSingleProductImages(id, isSwiperInline) / getActiveImage(mediaItemId)#

What they do
Product-single gallery helpers (only relevant when used in product section contexts).

updateHeaderHeight() / updateStickyElementTop() / updateStickyState() / scrollToTop(selector) / updateActiveButtonOnScroll()#

What they do
Sticky/scroll helpers for product single sections (only relevant when isProductSection === true).

increaseQuantity(groupVariant = {}) / decreaseQuantity(groupVariant = {})#

What they do
Adjust internal quantity using quantityConstraints.additive.step and min/max.

debounceUpdateProduct(...) / updateQuantity(...)#

What they do
Debounce and validate quantity updates.
When checkQuantity is true, calls servicesreusabledefault.updateProductQuantity(...) with an Axios cancel token.
Uses $store.toast on failures.

Global Alpine stores#

This reusable uses:
$store.toast
Used for add-to-cart and quantity validation error feedback.

Services / API calls#

servicesreusabledefault.addToCart(...)
servicesreusabledefault.updateProductQuantity(...)

Dependencies#

Liquid: Reusables/ProductListItem/Default.liquid
JS: Reusables/ProductListItem/Default.js
Translations: Reusables/ProductListItem/Default.json
Nested reusables:
Reusables/ProductComparisonButton/Default
Reusables/WishlistButton/Default
Reusables/ShoppingListsButton/Default
Vendor JS: Swiper (dimension carousels)

Notes#

The template assumes product.mediaItems[0] is an image; for best results the first media item should be an Image.
colorExists affects whether the mobile color-dot block or a placeholder is shown.
Keep Liquid and JS contracts in sync when changing product fields.
Modified at 2026-04-14 13:18:56
Previous
ProductGridItem
Next
ShoppingListsButton
Built with