8

I am trying to make auto select first child product from the configurable product in product detail page.

Is this possible?

2 Answers 2

24

For Dropdown:

Override this file to your theme:

vendor/magento/module-configurable-product/view/frontend/web/js/configurable.js

your theme file location will be:

app/design/frontend/[vendor]/[theme]/Magento_ConfigurableProduct/web/js/configurable.js

Replace the _fillSelect method under configurable.js

_fillSelect: function (element) {
    var attributeId = element.id.replace(/[a-z]*/, ''),
        options = this._getAttributeOptions(attributeId),
        prevConfig,
        index = 1,
        allowedProducts,
        i,
        j;

    this._clearSelect(element);
    element.options[0] = new Option('', '');
    element.options[0].innerHTML = this.options.spConfig.chooseText;
    prevConfig = false;

    if (element.prevSetting) {
        prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
    }

    if (options) {
        for (i = 0; i < options.length; i++) {
            allowedProducts = [];
            if (prevConfig) {
                for (j = 0; j < options[i].products.length; j++) {
                    // prevConfig.config can be undefined
                    if (prevConfig.config &&
                        prevConfig.config.allowedProducts &&
                        prevConfig.config.allowedProducts.indexOf(options[i].products[j]) > -1) {
                        allowedProducts.push(options[i].products[j]);
                    }
                }
            } else {
                allowedProducts = options[i].products.slice(0);
            }

            if (allowedProducts.length > 0) {
                options[i].allowedProducts = allowedProducts;
                element.options[index] = new Option(this._getOptionLabel(options[i]), options[i].id);
                if (typeof options[i].price !== 'undefined') {
                    element.options[index].setAttribute('price', options[i].prices);
                }

                element.options[index].config = options[i];




                index++;
            }
            // Code added to select option
            if (i == 0) {
                this.options.values[attributeId] = options[i].id;
            }   
        }
        //Code added to check if configurations are set in url and resets them if needed 
        if (window.location.href.indexOf('#') !== -1) {this._parseQueryParams(window.location.href.substr(window.location.href.indexOf('#') + 1));}
    }

},

For Swatch: Override the below file to your theme

/module-swatches/view/frontend/web/js/SwatchRenderer.js

And update the method _RenderControls

_RenderControls: function () {
    var $widget = this,
        container = this.element,
        classes = this.options.classes,
        chooseText = this.options.jsonConfig.chooseText,
        selectedArray = []; // Variable declation for autoselect element array

    $widget.optionsMap = {};

    $.each(this.options.jsonConfig.attributes, function () {
        var item = this,
            controlLabelId = 'option-label-' + item.code + '-' + item.id,
            options = $widget._RenderSwatchOptions(item, controlLabelId),
            select = $widget._RenderSwatchSelect(item, chooseText),
            input = $widget._RenderFormInput(item),
            listLabel = '',
            label = '';

        // Show only swatch controls
        if ($widget.options.onlySwatches && !$widget.options.jsonSwatchConfig.hasOwnProperty(item.id)) {
            return;
        }

        if ($widget.options.enableControlLabel) {
            label +=
                '<span id="' + controlLabelId + '" class="' + classes.attributeLabelClass + '">' +
                    item.label +
                '</span>' +
                '<span class="' + classes.attributeSelectedOptionLabelClass + '"></span>';
        }

        if ($widget.inProductList) {
            $widget.productForm.append(input);
            input = '';
            listLabel = 'aria-label="' + item.label + '"';
        } else {
            listLabel = 'aria-labelledby="' + controlLabelId + '"';
        }

        // Create new control
        container.append(
            '<div class="' + classes.attributeClass + ' ' + item.code + '" ' +
                 'attribute-code="' + item.code + '" ' +
                 'attribute-id="' + item.id + '">' +
                label +
                '<div aria-activedescendant="" ' +
                     'tabindex="0" ' +
                     'aria-invalid="false" ' +
                     'aria-required="true" ' +
                     'role="listbox" ' + listLabel +
                     'class="' + classes.attributeOptionsWrapper + ' clearfix">' +
                    options + select +
                '</div>' + input +
            '</div>'
        );

        $widget.optionsMap[item.id] = {};

        // Aggregate options array to hash (key => value)
        $.each(item.options, function () {
            if (this.products.length > 0) {
                $widget.optionsMap[item.id][this.id] = {
                    price: parseInt(
                        $widget.options.jsonConfig.optionPrices[this.products[0]].finalPrice.amount,
                        10
                    ),
                    products: this.products
                };
            }
        });
        //Create array for Autoselect swatch
        selectedArray.push($widget.element.find('[attribute-id=' + item.id + '] .swatch-option')[0]);
    });


    // Connect Tooltip
    container
        .find('[option-type="1"], [option-type="2"], [option-type="0"], [option-type="3"]')
        .SwatchRendererTooltip();

    // Hide all elements below more button
    $('.' + classes.moreButton).nextAll().hide();

    // Handle events like click or change
    $widget._EventListener();

    // Rewind options
    $widget._Rewind(container);

    //Emulate click on all swatches from Request
    $widget._EmulateSelected($.parseQuery());
    $widget._EmulateSelected($widget._getSelectedAttributes());

    //Trigger click for Autoselect first option swatch
    $.each(selectedArray, function () {
        if(this != undefined) this.click();
    });

},
22
  • Hello, i am using module swatch , the above code is for drop downs i guess, can we make it work for swatches also? Commented Jul 2, 2018 at 15:42
  • 1
    After upgrading to 2.3.1 this method stopped working for some dropdowns. I'm not entirely sure why but the fix was easy, just change if (i == 0) to if (i === 0) Commented Apr 24, 2019 at 16:08
  • 1
    Thanks this code is working perfectly for magento 2.3 also
    – kushal
    Commented May 1, 2019 at 11:53
  • 1
    Code is working perfectly
    – Shorabh
    Commented Jul 18, 2019 at 11:33
  • 1
    Thanks sukumar instead of theme how to override the same function from custom module? Commented Dec 26, 2019 at 14:01
0

For a simpler solution for swatches, you can add a JS file in your (child)theme for layout catalog_product_view.xml

JS file content:

require(["jquery"],function($){
  $(document).on('swatch.initialized', function() { 
    $(".swatch-attribute.color .swatch-option").first().not(".selected").click();
  });
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.