Skip to content

Bundle Items

Use bundle_items module to insert a module that displays products included in the currently viewed bundle on a page. This module is available only within a bundle card.

Configuration parameters

title

string a title of the module. If not specified no title will be displayed.

shouldDisplayDescription

int if set to 1 a module description will be displayed.

description

string represents a text content of the description element.

isProductQuantityVisible

int if set to 1 the element allowing to choose product quantity will be displayed.

hasProducerName

int if set to 1 the products in the given bundle will have their producer name displayed.

hasRegularPriceOutsideBundle

int if set to 1 the products in the given bundle will have their regular prices outside the bundle displayed.

hasCheaperInTheBundleInfo

int if set to 1 a tag indicating that the product is cheaper in the bundle will appear next to each product

hasShortDescription

int if set to 1 the products in the given bundle will have their short description displayed.

Module source code

{% from "@macros/product_bundle_item_tile.twig" import product_bundle_item_tile %}
{% from "@macros/product_quantity.twig" import product_quantity %}
{% from "@macros/icon.twig" import icon %}

{% set product = ObjectApi.getProduct(product_id) %}
{% set globalPricesSettings = ObjectApi.getProductPricesSettings() %}
{% set notificationSettings = ObjectApi.getNotificationSettings() %}
{% set basketSettings = ObjectApi.getBasketSettings() %}

{% set moduleInstanceId = 'bundle-items-' ~ moduleInstance %}
{% set groupFlashMessengerName = "group-flash-messenger-#{moduleInstanceId}" %}

{% if product.bundle.items|length %}
    {% set buyActionButton %}
        {% if product.packageQuantity %}
            {% set quantity = product.packageQuantity %}
        {% else %}
            {% set quantity = 1 %}
        {% endif %}

        <buy-button
                quantity="{{ quantity }}"
                product-id="{{ product.id }}"
                variant-id="{{ product.variant.id }}"
                is-buyable="{{ product.availability.isAvailable }}"
                has-bundle-items="1"
                {% if product.options.count > 0 %}
                    has-product-variants
                {% endif %}
                {% if not product.isAvailable and not product.options.count > 0 %}
                    hidden
                {% endif %}
                on-interaction
        >
            <div class="product-actions__add-to-basket{% if not globalPricesSettings.showPricesToUnregistered %}mr-xs-2{% endif %}">
                <button type="button" class="btn btn_primary">{{ translate('Add to cart') }}</button>
            </div>
        </buy-button>
    {% endset %}

    <div class="bundle-items__container" data-scroll="product-bundles">
        <div class="bundle-items__header module__header accordion__toggler">
            <div class="module__header-title">
                <span class="module__header_highlight">{{ moduleConfig.title }} ({{ product.bundle.items|length }})</span>
            </div>
        </div>

        {% if moduleConfig.shouldDisplayDescription %}
            <div class="description mb-xs-1">{{ moduleConfig.description }}</div>
        {% endif %}

        <flash-messenger class="flash-messenger mb-xs-1" name="{{ groupFlashMessengerName }}"></flash-messenger>

        <div class="bundle-items__content accordion-content">
            <product-bundles class="bundle-items">
                <div class="bundle-items__list">
                    {% for bundleItem in product.bundle.items %}
                        {% if not loop.first %}
                            <h2 class="bundle-items__plus">+</h2>
                        {% endif %}

                        {% set variantId = moduleInstanceId ~ "-#{bundleItem.variant.product.id}" %}

                        {{ 
                            product_bundle_item_tile(
                                bundleItem,
                                moduleConfig|merge({
                                    instanceId: variantId,
                                    groupFlashMessengerName
                                }
                            ))
                        }}
                    {% endfor %}
                </div>

                <div class="grid">
                    <div class="grid__row grid__row_xs-grow grid__row_xs-hcenter">
                        {% if basketSettings.isBuyingEnabled %}
                            {% if product.isAvailable %}
                                {% if moduleConfig.isProductQuantityVisible %}
                                    <div class="grid__col grid__col_xs-12 grid__col_sm-auto grid__col_xs-hcenter grid__col_xs-vbottom mb-xs-3 mb-sm-0">
                                        {{ product_quantity(product, { moduleInstance: moduleInstanceId, noLabel: true }) }}
                                    </div>
                                {% endif %}
                                <div class="grid__col grid__col_xs-12 grid__col_sm-auto grid__col_xs-hcenter grid__col_xs-vbottom">
                                    <auth-controller>
                                        <div slot="logged-in" hidden>
                                            {{ buyActionButton }}
                                        </div>
                                        <div slot="logged-out">
                                            {% if globalPricesSettings.showPricesToUnregistered %}
                                                {{ buyActionButton }}
                                            {% endif %}
                                        </div>
                                    </auth-controller>
                                </div>
                            {% elseif not notificationSettings.getIsProductNotificationEnabled() or not product.availability.isNotificationEnabled %}
                                <div class="grid__col grid__col_xs-12 grid__col_sm-auto grid__col_xs-hcenter grid__col_xs-vbottom">
                                    <span class="btn btn_full-width btn_special btn_special-disabled">
                                        {{ translate('Unavailable') }}
                                    </span>
                                </div>
                            {% endif %}

                            {% if notificationSettings.getIsProductNotificationEnabled() %}
                                <div class="grid__col grid__col_xs-12 grid__col_sm-auto grid__col_xs-hcenter grid__col_xs-vbottom">
                                    <availability-notifier-btn
                                            product-name="{{ product.name }}"
                                            product-image="{{ product.featuredImage.webpThumbnailUrl(120, 120) }}"
                                            product-id="{{ product.id }}"
                                            product-variant-id="{{ product.variant.id }}"
                                            {% if not product.availability.isNotificationEnabled or product.isAvailable %}
                                                hidden
                                            {% endif %}>
                                        <button class="btn btn_secondary" slot="subscribe">
                                            {{ icon('icon-bell', {
                                                classNames: ['btn__icon', 'btn__icon_left']
                                            }) }}
                                            {{ translate('Notify me when available') }}
                                        </button>
                                        <button class="btn btn_outline" slot="unsubscribe" hidden>
                                            {{ icon('icon-bell-off', {
                                                classNames: ['btn__icon', 'btn__icon_left']
                                            }) }}
                                            {{ translate('Opt out of notifications') }}
                                        </button>
                                    </availability-notifier-btn>
                                </div>
                            {% endif %}
                        {% else %}
                            <div class="grid__col grid__col_xs-12 grid__col_sm-auto grid__col_xs-hcenter grid__col_xs-vbottom">
                                <span class="btn btn_full-width btn_special btn_special-disabled">
                                    {{ translate('Cart disabled') }}
                                </span>
                            </div>
                        {% endif %}
                    </div>
                </div>
            </product-bundles>
        </div>
    </div>
{% endif %}

Webcomponents reference

Macros reference

Used Object Api methods

Used styles

Module configuration schema

[
    {
        "state": "unfolded",
        "label": "General settings",
        "elements": [
            {
                "type": "text",
                "label": "Module title",
                "name": "title",
                "defaultValue": "Products in the bundle",
                "supportsTranslations": 1
            },
            {
                "type": "checkbox",
                "name": "shouldDisplayDescription",
                "label": "Display additional description below the module title",
                "defaultValue": 0,
                "children": [
                    {
                        "type": "textarea",
                        "name": "description",
                        "label": "Description",
                        "isHidden": 1,
                        "supportsTranslations": 1,
                        "relations": [
                            {
                                "parentName": "shouldDisplayDescription",
                                "parentValueToActionsMap": [
                                    {
                                        "value": 0,
                                        "actions": ["setHidden", "setDisabled"]
                                    },
                                    {
                                        "value": 1,
                                        "actions": ["setVisible", "setAvailable"]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            },
            {
                "type": "checkbox",
                "name": "isProductQuantityVisible",
                "label": "Display the \"Quantity\" field",
                "defaultValue": 1,
                "hint": "If the \"Quantity\" field is hidden, each click on the \"Add to Cart\" button will add one product (or product unit). The customer will be able to change this quantity in the cart."
            }
        ]
    },
    {
        "state": "unfolded",
        "label": "Product tile",
        "elements": [
            {
                "type": "infobox",
                "name": "infobox",
                "options": {
                    "type": "blank",
                    "message": "#### Related settings in the admin panel%s- changing phrases in [translations](%s)%s- showing prices net\/gross in [tax rates settings](%s)%s- setting [product availability statuses](%s)",
                    "placeholderValues": [
                        "\n",
                        "\/admin\/configLanguages\/list",
                        "\n",
                        "\/admin\/configTax\/list",
                        "\n",
                        "\/admin\/configAvailabilities\/list"
                    ]
                }
            },
            {
                "type": "header",
                "name": "productOptions",
                "label": "Display for every product:",
                "children": [
                    {
                        "type": "checkbox",
                        "name": "hasProducerName",
                        "label": "vendor's name",
                        "defaultValue": 1
                    },
                    {
                        "type": "checkbox",
                        "name": "hasRegularPriceOutsideBundle",
                        "label": "regular price outside the bundle",
                        "defaultValue": 1
                    },
                    {
                        "type": "checkbox",
                        "name": "hasCheaperInTheBundleInfo",
                        "label": "\"Cheaper in the bundle!\" information",
                        "defaultValue": 1
                    },
                    {
                        "type": "checkbox",
                        "name": "hasShortDescription",
                        "label": "short description",
                        "defaultValue": 1
                    }
                ]
            }
        ]
    }
]