You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Magento 2技术需求:在商品分类页展示自定义选项并实现价格联动加购

Display Custom Options on Magento 2 Category Page with Dynamic Pricing & Direct Add-to-Cart

Alright, let’s break down how to build this feature step by step—showing product custom options on category pages, updating prices in real-time when options change, and letting customers add products to cart right from the category page. I’ve implemented similar workflows before, so here’s a practical, hands-on guide:

Step 1: Override the Category Product List Template

First rule of Magento development: never edit core files directly. Copy the default product list template to your custom theme to keep changes safe during updates:

# Copy core template to your theme directory
cp vendor/magento/module-catalog/view/frontend/templates/product/list.phtml app/design/frontend/[YourVendor]/[YourTheme]/Magento_Catalog/templates/product/list.phtml

Open the copied template, and locate the foreach ($_productCollection as $_product) loop—this is where we’ll inject the custom options display.

Step 2: Render Product Custom Options in the Template

Inside the product loop, add code to load and render the product’s custom options. We’ll handle common option types (dropdown, radio, checkbox) and include required field indicators:

<?php $_options = $_product->getOptions(); ?>
<?php if (!empty($_options)): ?>
    <div class="product-custom-options">
        <?php foreach ($_options as $_option): ?>
            <?php if ($_option->getIsVisible()): ?>
                <div class="option-group">
                    <label class="option-label">
                        <?= $_option->getTitle() ?>
                        <?php if ($_option->getIsRequired()): ?>
                            <span class="required">*</span>
                        <?php endif; ?>
                    </label>
                    <?php if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_DROP_DOWN): ?>
                        <select name="options[<?= $_option->getId() ?>]" class="custom-option" data-option-id="<?= $_option->getId() ?>">
                            <option value="">-- Select an option --</option>
                            <?php foreach ($_option->getValues() as $_value): ?>
                                <option value="<?= $_value->getId() ?>" data-price="<?= $_value->getPrice() ?>" data-price-type="<?= $_value->getPriceType() ?>">
                                    <?= $_value->getTitle() ?>
                                    <?php if ($_value->getPrice() != 0): ?>
                                        (<?= $_value->getPriceType() == 'percent' ? $_value->getPrice() . '%' : $_product->getPriceInfo()->getPrice('final_price')->getCurrency()->format($_value->getPrice()) ?>)
                                    <?php endif; ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                    <?php elseif ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_RADIO || $_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_CHECKBOX): ?>
                        <?php foreach ($_option->getValues() as $_value): ?>
                            <div class="option-item">
                                <input type="<?= $_option->getType() == 'radio' ? 'radio' : 'checkbox' ?>"
                                       name="options[<?= $_option->getId() ?>]<?= $_option->getType() == 'checkbox' ? '[]' : '' ?>"
                                       value="<?= $_value->getId() ?>"
                                       class="custom-option"
                                       data-option-id="<?= $_option->getId() ?>"
                                       data-price="<?= $_value->getPrice() ?>"
                                       data-price-type="<?= $_value->getPriceType() ?>">
                                <label><?= $_value->getTitle() ?>
                                    <?php if ($_value->getPrice() != 0): ?>
                                        (<?= $_value->getPriceType() == 'percent' ? $_value->getPrice() . '%' : $_product->getPriceInfo()->getPrice('final_price')->getCurrency()->format($_value->getPrice()) ?>)
                                    <?php endif; ?>
                                </label>
                            </div>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </div>
            <?php endif; ?>
        <?php endforeach; ?>
    </div>
<?php endif; ?>

Step 3: Add Dynamic Price Update Logic

Now we need JavaScript to listen for option changes and recalculate the product price in real-time. Add this script either directly in the list.phtml template or your theme’s custom JS file:

require(['jquery', 'Magento_Catalog/js/price-utils'], function($, priceUtils) {
    $(document).on('change', '.custom-option', function() {
        var $productItem = $(this).closest('.product-item');
        var productId = $productItem.data('product-id');
        var basePrice = parseFloat($productItem.find('.price-box .price').data('base-price'));
        var finalPrice = basePrice;

        // Calculate total price adjustment from selected options
        $productItem.find('.custom-option:checked, .custom-option option:selected').each(function() {
            var price = parseFloat($(this).data('price'));
            var priceType = $(this).data('price-type');

            if (priceType === 'percent') {
                finalPrice += (basePrice * price / 100);
            } else {
                finalPrice += price;
            }
        });

        // Update displayed price with Magento's formatting
        var formattedPrice = priceUtils.formatPrice(finalPrice, window.priceFormat);
        $productItem.find('.price-box .price').html(formattedPrice);
    });
});

Don’t forget to add these data attributes to your product container and price element in list.phtml:

<!-- Add to product item container -->
<div class="product-item" data-product-id="<?= $_product->getId() ?>">

<!-- Update price element to store base price -->
<span class="price" data-base-price="<?= $_product->getFinalPrice() ?>">
    <?= /* @escapeNotVerified */ $block->getProductPrice($_product) ?>
</span>

Step 4: Modify Add-to-Cart Form to Include Options

The default category add-to-cart button doesn’t pass custom options, so wrap the product details and options in a proper form:

<?php if ($_product->isSaleable()): ?>
    <form data-role="tocart-form" action="<?= $block->getAddToCartUrl($_product) ?>" method="post" class="product-item-form">
        <?= $block->getBlockHtml('formkey') ?>
        <input type="hidden" name="product" value="<?= $_product->getId() ?>">
        <input type="hidden" name="related_product" id="related-products-field" value="">

        <!-- Product image, name, price, and custom options go here -->

        <button type="submit" title="<?= $block->escapeHtml(__('Add to Cart')) ?>" class="action tocart primary">
            <span><?= /* @escapeNotVerified */ __('Add to Cart') ?></span>
        </button>
    </form>
<?php endif; ?>

Ensure customers select required options before adding to cart with this validation script:

$(document).on('submit', '.product-item-form', function(e) {
    var $form = $(this);
    var isValid = true;

    $form.find('.option-group:has(.required)').each(function() {
        var $option = $(this).find('.custom-option');
        var selectedValue = $option.is(':checkbox') ? $option.filter(':checked').val() : $option.val();

        if (!selectedValue) {
            isValid = false;
            $(this).find('.option-label').addClass('error');
            alert('Please select a value for the required option: ' + $(this).find('.option-label').text().trim());
        } else {
            $(this).find('.option-label').removeClass('error');
        }
    });

    if (!isValid) {
        e.preventDefault();
    }
});

Final Checks

  • Clear Magento cache to apply all changes:
php bin/magento cache:clean
php bin/magento cache:flush
  • Test all edge cases: required options, fixed/percent price adjustments, different option types, and add-to-cart functionality.

内容的提问来源于stack exchange,提问作者Raina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:46:50