Skip to content

Magento2.4: How to show custom dropdown of configurable product size swatch?

I’m trying to create a custom dropdown for the size swatch of configurable products.
I was getting an error on my iPhone which doesn’t show the size attribute on mobile so I was converting the size swatch to a phtml file rather than javascript, some developers already created the custom drop-down for the colour swatch and I just duplicated the login.

Here is the code, and error

app/design/frontend/vendor/module/Magento_Swatches/templates/product/view/renderer.phtml

<?php
$configurableViewModel = $block->getConfigurableViewModel();

$options = $block->getJsonConfig();
$optionsConfig = json_decode($options, true)['attributes'];
$product = $block->getProduct();
$colorSwatch = $this->getLayout()->getBlock('color.images');
$colorImages = $colorSwatch->getColorImg($product);
?>
<?php foreach ($optionsConfig as $attributeId => $attribute): ?>
<?php if ($attribute['code'] === 'attr_couleur'): ?>
    <div>
        <div class="custom-select-wrapper" id="custom-select-<?= $block->escapeHtmlAttr($attributeId) ?>">
            <div class="custom-select">
                <div class="custom-select__trigger">
                    <span><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></span>
                    <div class="arrow"></div>
                </div>
                <div class="custom-options">
                    <span class="custom-option"><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></span>
                    <?php foreach ($attribute['options'] as $option): ?>
                        <?php
                        $colorImage = isset($colorImages[$option['id']]) ? $colorImages[$option['id']]['image'] : '';
                        $colorName = isset($colorImages[$option['id']]) ? $colorImages[$option['id']]['name'] : $option['label'];
                        ?>
                        <span class="custom-option" data-value="<?= $block->escapeHtmlAttr($option['id']) ?>" data-image="<?= $block->escapeUrl($colorImage) ?>">
                                    <img src="<?= $block->escapeUrl($colorImage) ?>" alt="<?= $block->escapeHtml($colorName) ?>">
                                    <?= $block->escapeHtml($colorName) ?>
                    </span>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>

        <select id="custom-couleur" class="custom-couleur super-attribute-select">
            <option value=""><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></option>
            <?php foreach ($attribute['options'] as $option): ?>
                <option value="<?= $block->escapeHtmlAttr($option['id']) ?>">
                    <?= $block->escapeHtml($option['label']) ?>
                </option>
            <?php endforeach; ?>
        </select>
    </div>
<?php elseif ($attribute['code'] === 'attr_size'): ?>
    <div>
        <div class="custom-select-wrapper-size" id="custom-select-<?= $block->escapeHtmlAttr($attributeId) ?>">
            <div class="custom-select-size">
                <div class="custom-select__trigger-size">
                    <span><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></span>
                    <div class="arrow"></div>
                </div>
                <div class="custom-options-size">
                    <span class="custom-option-size"><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></span>
                    <?php foreach ($attribute['options'] as $option): ?>
                        <span class="custom-option-size" data-value="<?= $block->escapeHtmlAttr($option['id']) ?>">
                            <?= $block->escapeHtml($option['label']) ?>
                        </span>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>

        <select id="custom-size" class="custom-size super-attribute-select" style="display: none">
            <option value=""><?= $block->escapeHtml(__('Choose a ')).$block->escapeHtml(strtolower($attribute['label'])) ?></option>
            <?php foreach ($attribute['options'] as $option): ?>
                <option value="<?= $block->escapeHtmlAttr($option['id']) ?>">
                    <?= $block->escapeHtml($option['label']) ?>
                </option>
            <?php endforeach; ?>
        </select>
    </div>
<?php endif; ?>
<script type="text/javascript">
    require(['jquery'], function($) {
        $(document).ready(function() {

            $('.custom-couleur').on('change', function() {
                console.log($(this).val());
                var optionId = $(this).val();
                if(optionId > 0) {
                    $('[data-option-id="' + optionId + '"]').click();
                }else{
                    $('#custom-couleur option:first').click();
                }
            });

            var $wrapper = $('.custom-select-wrapper');
            var $select = $wrapper.siblings('select.super-attribute-select');
            var $customSelect = $wrapper.find('.custom-select');
            var $customSelectTrigger = $customSelect.find('.custom-select__trigger');
            var $customOptions = $customSelect.find('.custom-options');
            var $txtDefault = $select.find('option:first-child').text();
            function updateCustomSelect() {
                var $selectedOption = $select.find('option:selected');
                var value = $selectedOption.val();
                var text = $selectedOption.text();
                var $customOption = $customOptions.find('.custom-option[data-value="' + value + '"]');
                var imgSrc = $customOption.find('img').attr('src');


                $customOptions.find('.custom-option').removeClass('selected');
                $customOption.addClass('selected');
                if (value) {
                    $customSelectTrigger.find('span').html('<img src="' + imgSrc + '" alt="' + text + '"> ' + text);
                    // Change main product image
                    /*
                    var largeImageSrc = $customOption.data('image');
                    $('.gallery-placeholder img.gallery-placeholder__image').attr('src', largeImageSrc);
                    */
                } else {
                    $customSelectTrigger.find('span').text($txtDefault);
                }

                // Mettre à jour le nombre de couleurs restantes
                /* var remainingColors = $customOptions.find('.custom-option').length - 1;
                $customSelectTrigger.find('.remaining-colors').remove();
                if (remainingColors > 0) {
                    $customSelectTrigger.append('<span class="remaining-colors">+ ' + remainingColors + ' Couleurs</span>');
                } */
            }

            $customSelectTrigger.on('click', function() {
                $customSelect.toggleClass('open');
            });

            $customOptions.on('click', '.custom-option', function() {
                var value = $(this).data('value');
                $select.val(value).trigger('change');
                $customSelect.removeClass('open');
                $customSelectTrigger.find('.arrow').addClass('selected');
            });

            $select.on('change', updateCustomSelect);

            updateCustomSelect();
        });
    });
</script>

<script type="text/javascript">
    require(['jquery'], function($) {
        $(document).ready(function() {

            var $wrapper = $('.custom-select-wrapper-size');
            var $select = $wrapper.siblings('select.custom-size');
            var $customSelect = $wrapper.find('.custom-select-size');
            var $customSelectTrigger = $customSelect.find('.custom-select__trigger-size');
            var $customOptions = $customSelect.find('.custom-options-size');
            var $txtDefault = $select.find('option:first-child').text();

            $('.custom-size').on('change', function() {
                // console.log($(this).val());
                var optionId = $(this).val();
                if(optionId > 0) {
                    $('[data-option-id="' + optionId + '"]').click();
                }else{
                    $('#custom-size option:first').click();
                }
            });
            $('.custom-size').on('change', function() {
                var selectedValue = $(this).val();
                console.log("Selected custom size value:", selectedValue);

                var $swatchSelect = $('select.attr_size');
                var $optionToSelect = $swatchSelect.find('option[data-option-id="' + selectedValue + '"]');
                console.log($optionToSelect);

                if ($optionToSelect.length > 0) {
                    $swatchSelect.val($optionToSelect.val());
                    console.log("Swatch dropdown updated to:", $optionToSelect.text());

                    var $swatchOption = $('.swatch-opt');
                    var $swatchDiv = $swatchOption.find('div.attr_size');
                    $swatchDiv.attr('data-option-selected', selectedValue);
                    console.log("Updated div.attr_size with data-option-selected:", selectedValue);
                } else {
                    console.log("No matching option found in the swatch dropdown for value:", selectedValue);
                }
            });

            function updateCustomSelectSize() {
                var $selectedOption = $select.find('option:selected');
                var value = $selectedOption.val();
                var text = $selectedOption.text();
                var $customOption = $customOptions.find('.custom-option-size[data-value="' + value + '"]');

                $customOptions.find('.custom-option-size').removeClass('selected');
                $customOption.addClass('selected');
                if (value) {
                    $customSelectTrigger.find('span').html(text);
                } else {
                    $customSelectTrigger.find('span').text($txtDefault);
                }
            }

            $customSelectTrigger.on('click', function() {
                $customSelect.toggleClass('open');
            });

            $customOptions.on('click', '.custom-option-size', function() {
                var value = $(this).data('value');
                $select.val(value).trigger('change');
                $customSelect.removeClass('open');
                $customSelectTrigger.find('.arrow').addClass('selected');
            });

            $select.on('change', updateCustomSelectSize);

            updateCustomSelectSize();
        });
    });
</script>