List Context Products¶
Availability:
Use list_context_products module to display a list of products depending on the context you are in, with pagination and a possibility to select a sort option. The displayed products will differ depending on whether the module is placed in the context of a category, collection or promotion list. The displayed products will It uses sort_select macro, pagination macro and ist_grid macro. Additionally, you can upload a banner that will be displayed at a specific position per device, with customizable width and height.
Configuration parameters¶
phoneProductsCountPerRow¶
int An indicator of how many products should fit in one row of the grid on phone resolution.
tabletProductsCountPerRow¶
int An indicator of how many products should fit in one row of the grid on tablet resolution.
laptopProductsCountPerRow¶
int An indicator of how many products should fit in one row of the grid on laptop resolution.
desktopProductsCountPerRow¶
int An indicator of how many products should fit in one row of the grid on desktop resolution.
shouldShowPaginationAboveProductList¶
int if set to 1 an additional small pagination will be rendered above the list next to the sort select.
hasFavouriteIcon¶
int if set to 1 the favourite icon is displayed
hasSkuCode¶
int if set to 1 a sku code is displayed
hasProducerCode¶
int if set to 1 a producer code is displayed
hasProducerName¶
int if set to 1 a producer name is displayed
hasRegularPriceWhilePromotionActive¶
int if set to 1 the regular price will be displayed on the product along with promotional price
hasPercentageDiscountValue¶
int if set to 1 a percentage value of the discount will be displayed on the product alongside the promotional price
hasTaxInfo¶
int if set to 1 tax info is displayed
hasUnitPrice¶
int if set to 1 the unit price is displayed
hasPriceWithoutDeliveryInfo¶
int if set to 1 the information about unaccounted shipping costs is displayed
hasAddToBasketButton¶
int if set to 1 add to basket button is displayed
hasAvailabilityStatus¶
int if set to 1 the availability status is displayed
shouldShortenLongProductName¶
int if set to 1 a long product name will be trimmed to take no more than two lines
hasImageBackgroundColor¶
int If set to 1, a background color will be applied to the product image.
imageBackgroundColor¶
colorPicker Allows you to select the background color for the product image.
specialImage¶
object An object containing following image properties:
widthfloat type, represents the width of the imageheightfloat type, represents the height of the imagefile_namestring type, represents the name of the image fileuploaded_filestring type, represents the name of the uploaded image file
specialImageAlt¶
string Alternative text for the banner image.
allowSpecialImageAsLink¶
int If set to 1, the banner image will be rendered as a link.
link¶
string The URL to which the banner image will link.
shouldOpenLinkInTheSameTab¶
int If set to 1, the link will open in the same browser tab.
specialTileSize¶
select Allows you to choose the banner tile size: tile (default), 2horizontal (double width), 2vertical (double height) or square (square shape).
specialTilePositionMobile¶
int Sets the position of the banner tile in the product list for mobile devices.
specialTilePositionTablet¶
int Sets the position of the banner tile in the product list for tablet devices.
specialTilePositionLaptop¶
int Sets the position of the banner tile in the product list for laptop devices.
specialTilePositionDesktop¶
int Sets the position of the banner tile in the product list for desktop devices.
bannerBackgroundColor¶
colorPicker Allows you to set the background color of the banner tile.
Module source code¶
{% from "@macros/list_grid.twig" import list_grid %}
{% from "@macros/pagination.twig" import pagination %}
{% from "@macros/sort_select.twig" import sort_select %}
{% from "@macros/product_tile.twig" import product_tile %}
{% from "@macros/special_tile.twig" import special_tile %}
{% set productList = ObjectApi.getProducts(2) %}
{% set sortList = ObjectApi.getProductsListSortTypes() %}
{% set moduleInstanceId = 'list_context_products-' ~ moduleInstance %}
{% set specialTileIndexDesktop = moduleConfig.specialTilePositionDesktop %}
{% set specialTileIndexLaptop = moduleConfig.specialTilePositionLaptop %}
{% set specialTileIndexTablet = moduleConfig.specialTilePositionTablet %}
{% set specialTileIndexMobile = moduleConfig.specialTilePositionMobile %}
{% set specialTileSize = moduleConfig.specialTileSize %}
{% set isPhoneSpecialTileAtRowEnd = moduleConfig.phoneProductsCountPerRow != 0 and (specialTileIndexMobile % moduleConfig.phoneProductsCountPerRow == 0) %}
{% set isPhoneSpecialTileTooWide = specialTileSize in ['2horizontal', 'square'] and isPhoneSpecialTileAtRowEnd %}
{% set specialTileIndexMobile = (isPhoneSpecialTileTooWide and moduleConfig.phoneProductsCountPerRow > 1) ? specialTileIndexMobile - 1 : specialTileIndexMobile %}
{% set specialTileSizePhone = (isPhoneSpecialTileTooWide and moduleConfig.phoneProductsCountPerRow == 1) ? 'tile' : specialTileSize %}
{% set isTabletSpecialTileAtRowEnd = moduleConfig.tabletProductsCountPerRow != 0 and (specialTileIndexTablet % moduleConfig.tabletProductsCountPerRow == 0) %}
{% set isTabletSpecialTileTooWide = specialTileSize in ['2horizontal', 'square'] and isTabletSpecialTileAtRowEnd %}
{% set specialTileIndexTablet = (isTabletSpecialTileTooWide and moduleConfig.tabletProductsCountPerRow > 1) ? specialTileIndexTablet - 1 : specialTileIndexTablet %}
{% set specialTileSizeTablet = (isTabletSpecialTileTooWide and moduleConfig.tabletProductsCountPerRow == 1) ? 'tile' : specialTileSize %}
{% set isLaptopSpecialTileAtRowEnd = moduleConfig.laptopProductsCountPerRow != 0 and (specialTileIndexLaptop % moduleConfig.laptopProductsCountPerRow == 0) %}
{% set isLaptopSpecialTileTooWide = specialTileSize in ['2horizontal', 'square'] and isLaptopSpecialTileAtRowEnd %}
{% set specialTileIndexLaptop = (isLaptopSpecialTileTooWide and moduleConfig.laptopProductsCountPerRow > 1) ? specialTileIndexLaptop - 1 : specialTileIndexLaptop %}
{% set specialTileSizeLaptop = (isLaptopSpecialTileTooWide and moduleConfig.laptopProductsCountPerRow == 1) ? 'tile' : specialTileSize %}
{% set isDesktopSpecialTileAtRowEnd = moduleConfig.desktopProductsCountPerRow != 0 and (specialTileIndexDesktop % moduleConfig.desktopProductsCountPerRow == 0) %}
{% set isDesktopSpecialTileTooWide = specialTileSize in ['2horizontal', 'square'] and isDesktopSpecialTileAtRowEnd %}
{% set specialTileIndexDesktop = (isDesktopSpecialTileTooWide and moduleConfig.desktopProductsCountPerRow > 1) ? specialTileIndexDesktop - 1 : specialTileIndexDesktop %}
{% set specialTileSizeDesktop = (isDesktopSpecialTileTooWide and moduleConfig.desktopProductsCountPerRow == 1) ? 'tile' : specialTileSize %}
{%
set gridSettings = {
phoneItemsCountPerRow: moduleConfig.phoneProductsCountPerRow,
smallTabletItemsCountPerRow: moduleConfig.phoneProductsCountPerRow,
tabletItemsCountPerRow: moduleConfig.tabletProductsCountPerRow,
laptopItemsCountPerRow: moduleConfig.laptopProductsCountPerRow,
desktopItemsCountPerRow: moduleConfig.desktopProductsCountPerRow,
specialTileSizePhone: specialTileSizePhone,
specialTileSizeTablet: specialTileSizeTablet,
specialTileSizeLaptop: specialTileSizeLaptop,
specialTileSizeDesktop: specialTileSizeDesktop
}
%}
{%
set bannerSettings = {
href: moduleConfig.link,
alt: moduleConfig.specialImageAlt,
shouldOpenSpecialTileLinkInSameTab: moduleConfig.shouldOpenLinkInTheSameTab,
img: moduleConfig.specialImage.paths.original,
backgroundColor: moduleConfig.bannerBackgroundColor
}
%}
{% set hasMultiplePages = productList.pages > 1 %}
{% set hasFirstPageButton = hasMultiplePages and productList.page != 1 %}
{% set hasPrevPageButton = hasMultiplePages and productList.page != 1 %}
{% set hasNextPageButton = hasMultiplePages and productList.page != productList.pages %}
{% set hasLastPageButton = hasMultiplePages and productList.page != productList.pages %}
{%
set basePaginationOptions = {
firstPageButtonOptions: {
hasFirstPageButton,
firstButtonAriaLabel: translate('Return to the first product page')
},
prevPageButtonOptions: {
hasPrevPageButton: hasPrevPageButton,
prevButtonAriaLabel: translate('Previous products')
},
nextPageButtonOptions: {
hasNextPageButton: hasNextPageButton,
nextButtonAriaLabel: translate('Next products')
},
lastPageButtonOptions: {
hasLastPageButton,
lastButtonAriaLabel: translate('Go to the last page of products')
}
}
%}
{%
set topPaginationOptions = basePaginationOptions|merge({
firstPageButtonOptions: basePaginationOptions.firstPageButtonOptions|merge({
hasFirstPageButton: false
}),
lastPageButtonOptions: basePaginationOptions.lastPageButtonOptions|merge({
hasLastPageButton: false
}),
classNames: ['pagination_top'],
id: "list-context-products-pagination-top-#{moduleInstance}",
name: "list-context-products-pagination-top-#{moduleInstance}"
})
%}
{%
set bottomPaginationOptions = basePaginationOptions|merge({
prevPageButtonOptions: basePaginationOptions.prevPageButtonOptions|merge({
prevButtonText: translate('Previous')
}),
nextPageButtonOptions: basePaginationOptions.nextPageButtonOptions|merge({
nextButtonText: translate('Next')
}),
classNames: ['pagination_bottom'],
id: "list-context-products-pagination-bottom-#{moduleInstance}",
name: "list-context-products-pagination-bottom-#{moduleInstance}"
})
%}
{%
set productTileOptions = {
"hasFavouriteIcon": moduleConfig.hasFavouriteIcon,
"hasSkuCode": moduleConfig.hasSkuCode,
"hasProducerCode": moduleConfig.hasProducerCode,
"hasProducerName": moduleConfig.hasProducerName,
"hasRegularPriceWhilePromotionActive": moduleConfig.hasRegularPriceWhilePromotionActive,
"hasPercentageDiscountValue": moduleConfig.hasPercentageDiscountValue,
"hasTaxInfo": moduleConfig.hasTaxInfo,
"hasUnitPrice": moduleConfig.hasUnitPrice,
"hasPriceWithoutDeliveryInfo": moduleConfig.hasPriceWithoutDeliveryInfo,
"hasAddToBasketButton": moduleConfig.hasAddToBasketButton,
"hasAvailabilityStatus": moduleConfig.hasAvailabilityStatus,
"shouldShortenLongProductName": moduleConfig.shouldShortenLongProductName,
"imageBackgroundColor": moduleConfig.hasImageBackgroundColor ? moduleConfig.imageBackgroundColor : ''
}
%}
{% set deviceConfig = {
'desktop': { 'count': moduleConfig.desktopProductsCountPerRow, 'index': specialTileIndexDesktop },
'laptop': { 'count': moduleConfig.laptopProductsCountPerRow, 'index': specialTileIndexLaptop },
'tablet': { 'count': moduleConfig.tabletProductsCountPerRow, 'index': specialTileIndexTablet },
'mobile': { 'count': moduleConfig.phoneProductsCountPerRow, 'index': specialTileIndexMobile }
} %}
{% set tileTypes = deviceConfig
|map((config, device) => { 'class': device ~ '-only', 'index': config.index })
%}
{% set listItemsTemplate %}
{% for product in productList %}
{% set productIndex = loop.index %}
{% set availability = product.availability %}
{% if _context_id == 20 %}
{% set isInactive = not availability.isAvailable and availability.visibilityConfig.isSearchResultsItemGrey %}
{% else %}
{% set isInactive = not availability.isAvailable and availability.visibilityConfig.isListsItemGrey %}
{% endif %}
{% if bannerSettings.img %}
{% for tile in tileTypes %}
{% if productIndex == tile.index %}
{{ special_tile(tile.class, bannerSettings) }}
{% endif %}
{% endfor %}
{% endif %}
{{ product_tile(product, productTileOptions|merge({ instanceId: moduleInstanceId, imageSize: systemConfig.lSize, isInactive })) }}
{% endfor %}
{% if bannerSettings.img %}
{% for tile in tileTypes %}
{% if tile.index == productList|length + 1 or (tile.index == productList.itemCountPerPage + 1 and productList|length > productList.itemCountPerPage) %}
{{ special_tile(tile.class, bannerSettings) }}
{% endif %}
{% endfor %}
{% endif %}
{% endset %}
<h2 class="sr-only">{{ translate("List of products") }}</h2>
{% if productList|length %}
<product-list role="article" class="product-list">
<header class="product-list__header">
{{
sort_select(sortList, {
currentSortId: sort,
instanceId: moduleInstance
})
}}
{% if moduleConfig.shouldShowPaginationAboveProductList %}
{{ pagination(productList, topPaginationOptions) }}
{% endif %}
</header>
{{
list_grid(listItemsTemplate, {
grid: gridSettings,
className: 'product-list-grid'
})
}}
<footer class="product-list__footer">
{{ pagination(productList, bottomPaginationOptions) }}
</footer>
</product-list>
{% else %}
<span class="flash-message flash-message__notice">{{ translate("There are currently no products in this category") }}</span>
{% endif %}
Macros reference¶
Used Object Api methods¶
Used styles¶
Module configuration schema¶
[
{
"state": "unfolded",
"label": "General settings",
"elements": [
{
"type": "infobox",
"name": "infobox",
"options": {
"type": "blank",
"message": "#### Related settings in the admin panel%s- changing phrases in [translations](%s)%s- enabling additional sorting option in [product settings](%s)",
"placeholderValues": [
"\n",
"\/admin\/configLanguages\/list",
"\n",
"\/admin\/configProducts"
]
}
},
{
"type": "header",
"name": "headerMobile",
"label": "Mobile",
"options": {
"icon": "mobile_devices"
},
"children": [
{
"type": "number",
"name": "phoneProductsCountPerRow",
"label": "Number of products in the row",
"labelDescription": "Max. 2.",
"defaultValue": 1,
"validators": [
{ "type": "int" },
{ "type": "lessEqThan", "options": { "max": 2} },
{ "type": "greaterEqThan", "options": { "min": 1} }
]
}
]
},
{
"type": "header",
"name": "headerTablet",
"label": "Tablet",
"options": {
"icon": "tablet"
},
"children": [
{
"type": "number",
"name": "tabletProductsCountPerRow",
"label": "Number of products in the row",
"labelDescription": "Max. 4.",
"defaultValue": 3,
"validators": [
{ "type": "int" },
{ "type": "lessEqThan", "options": { "max": 4} },
{ "type": "greaterEqThan", "options": { "min": 1} }
]
}
]
},
{
"type": "header",
"name": "headerLaptop",
"label": "Laptop",
"options": {
"icon": "laptop"
},
"children": [
{
"type": "number",
"name": "laptopProductsCountPerRow",
"label": "Number of products in the row",
"labelDescription": "Max. 5.",
"defaultValue": 3,
"validators": [
{ "type": "int" },
{ "type": "lessEqThan", "options": { "max": 5} },
{ "type": "greaterEqThan", "options": { "min": 1} }
]
}
]
},
{
"type": "header",
"name": "headerDesktop",
"label": "Desktop",
"options": {
"icon": "desktop"
},
"children": [
{
"type": "number",
"name": "desktopProductsCountPerRow",
"label": "Number of products in the row",
"labelDescription": "Max. 6.",
"defaultValue": 4,
"validators": [
{ "type": "int" },
{ "type": "lessEqThan", "options": { "max": 6} },
{ "type": "greaterEqThan", "options": { "min": 1} }
]
}
]
},
{
"type": "checkbox",
"name": "shouldShowPaginationAboveProductList",
"label": "Display additional pagination above the product list",
"defaultValue": 1
}
]
},
{
"state": "unfolded",
"label": "Product tile",
"elements": [
{
"type": "infobox",
"name": "infoboxProductTile",
"options": {
"type": "blank",
"message": "#### Related settings in the admin panel%s- changing phrases in [translations](%s)%s- enabling vendor's code, 30-day lowest price and unit price calculation in [product settings](%s)%s- showing prices net\/gross in [tax rates settings](%s)%s- enabling the purchase option in [the orders settings](%s)%s- setting [product availability statuses](%s)",
"placeholderValues": [
"\n",
"\/admin\/configLanguages\/list",
"\n",
"\/admin\/configProducts",
"\n",
"\/admin\/configTax\/list",
"\n",
"\/admin\/configShopping\/list",
"\n",
"\/admin\/configAvailabilities\/list"
]
}
},
{
"type": "header",
"name": "productOptions",
"label": "Display for every product:",
"children": [
{
"type": "checkbox",
"name": "hasFavouriteIcon",
"label": "\"Add to favourites\" icon",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasSkuCode",
"label": "product code\/SKU",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "hasProducerCode",
"label": "vendor's code",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "hasProducerName",
"label": "vendor's name",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasRegularPriceWhilePromotionActive",
"label": "regular price (for products on sale)",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasPercentageDiscountValue",
"label": "by how many percent the price has changed (for products on sale)",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasTaxInfo",
"label": "tax class (if there is only one price: net or gross)",
"defaultValue": 0,
"hint": "Tax Class rate will be displayed regardless of these settings, if the store displays the net and gross prices at the same time."
},
{
"type": "checkbox",
"name": "hasUnitPrice",
"label": "unit price",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "hasPriceWithoutDeliveryInfo",
"label": "information that prices are quoted without delivery costs",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "hasAddToBasketButton",
"label": "\"Add to cart\" button",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasAvailabilityStatus",
"label": "availability status",
"defaultValue": 0
}
]
},
{
"type": "checkbox",
"name": "shouldShortenLongProductName",
"label": "Shorten long product names",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "hasImageBackgroundColor",
"label": "Add background color behind the image",
"defaultValue": 0,
"children": [
{
"type": "colorPicker",
"name": "imageBackgroundColor",
"label": "Background color",
"defaultValue": "@globalBodyBackgroundColor",
"options": {
"allowVariables": true
},
"relations": [
{
"parentName": "hasImageBackgroundColor",
"parentValueToActionsMap": [
{
"value": 0,
"actions": ["setHidden", "setDisabled"]
},
{
"value": 1,
"actions": ["setVisible", "setAvailable"]
}
]
}
]
}
]
}
]
},
{
"state": "unfolded",
"label": "Banner",
"elements": [
{
"type": "imageUpload",
"name": "specialImage",
"label": "Image <<SVE>>",
"isRequired": false,
"supportsTranslations": true,
"hint": "The file name is important for SEO and should describe the content of the image. Use dashes to separate words.",
"options": {
"requireImageSize" : true,
"allowedExtensions": [
"webp",
"svg",
"jpg",
"png",
"gif",
"jpeg"
]
}
},
{
"type": "text",
"name": "specialImageAlt",
"label": "Alternative image description (\"alt\")",
"supportsTranslations": true,
"isRequired": false,
"labelDescription": "For images with links, provide both the link destination and image description"
},
{
"type": "checkbox",
"name": "allowSpecialImageAsLink",
"label": "Image as a link",
"supportsTranslations": true,
"defaultValue": 0,
"children": [
{
"type": "text",
"name": "link",
"label": "Webpage URL",
"supportsTranslations": true,
"options": {
"placeholder": "https:\/\/ or \/"
},
"validators": [{"type" : "url", "options": { "allowRelativePath": true }}],
"relations": [
{
"parentName": "allowSpecialImageAsLink",
"parentValueToActionsMap": [
{
"value": 0,
"actions": [
"setHiddenAndOptional",
"setDisabled"
]
},
{
"value": 1,
"actions": [
"setVisibleAndRequired",
"setAvailable"
]
}
]
}
]
},
{
"type": "checkbox",
"name": "shouldOpenLinkInTheSameTab",
"label": "Open the link in the same tab",
"supportsTranslations": true,
"defaultValue": 1,
"hint": "Opening links in the same tab makes navigation easier: using the \"back\" button is possible. The customer can decide to open the page in a new tab.",
"relations": [
{
"parentName": "allowSpecialImageAsLink",
"parentValueToActionsMap": [
{
"value": 0,
"actions": [
"setHidden",
"setDisabled"
]
},
{
"value": 1,
"actions": [
"setVisible",
"setAvailable"
]
}
]
}
]
}
]
},
{
"name": "specialTileSize",
"type": "select",
"options": {
"selectOptions": [
{ "key" : "tile", "label" : "1 tile" },
{ "key" : "2horizontal", "label" : "2 tiles (horizontal)" },
{ "key" : "2vertical", "label" : "2 tiles (vertical)" },
{ "key" : "square", "label" : "4 tiles (square)" }
]
},
"label": "Banner size",
"supportsTranslations": true,
"defaultValue": "tile",
"hint": "The banner will be resized to 1 tile on devices where \"products per row\" is set to 1 product."
},
{
"type": "header",
"name": "headerTileMobile",
"label": "Mobile",
"options": {
"icon": "phone"
},
"children": [
{
"type": "number",
"name": "specialTilePositionMobile",
"label": "Position on the product list",
"hint": "Banner will display if there are sufficient products in the list. Example: for position 8, at least 7 products are needed.",
"defaultValue": 1,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 0} }
]
}
]
},
{
"type": "header",
"name": "headerTileTablet",
"label": "Tablet",
"options": {
"icon": "tablet"
},
"children": [
{
"type": "number",
"name": "specialTilePositionTablet",
"label": "Position on the product list",
"hint": "Banner will display if there are sufficient products in the list. Example: for position 8, at least 7 products are needed.",
"defaultValue": 1,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 0} }
]
}
]
},
{
"type": "header",
"name": "headerTileLaptop",
"label": "Laptop",
"options": {
"icon": "laptop"
},
"children": [
{
"type": "number",
"name": "specialTilePositionLaptop",
"label": "Position on the product list",
"hint": "Banner will display if there are sufficient products in the list. Example: for position 8, at least 7 products are needed.",
"defaultValue": 1,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 0} }
]
}
]
},
{
"type": "header",
"name": "headerTileDesktop",
"label": "Desktop",
"options": {
"icon": "desktop"
},
"children": [
{
"type": "number",
"name": "specialTilePositionDesktop",
"label": "Position on the product list",
"hint": "Banner will display if there are sufficient products in the list. Example: for position 8, at least 7 products are needed.",
"defaultValue": 1,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 0} }
]
}
]
},
{
"type": "colorPicker",
"name": "bannerBackgroundColor",
"label": "Background color behind image",
"labelDescription": "For images with transparency",
"defaultValue": "@globalBodyBackgroundColor",
"options": {
"allowVariables": true
}
}
]
}
]