Question

How to set drops downs on configurable products to be set to the first option rather than please select.

I have tried below code:

<script>
require(['jquery', 'jquery/ui'], function($){ 
  $('.product-add-form .field select').each(function(i, obj) {
    $(obj).find('option:eq(1)').prop('selected', true);
  });
});
</script>

However, this fails unless I time it out a bit which feels messy. It also does not update price when using this method.

Was it helpful?

Solution

Override configurable.js within the Configurable Products Module. The following code can be placed at around line 370 of configurable.js:

if (i == 0) {
    this.options.values[attributeId] = options[i].id;
}   

This is placed at the end of options loop so that the default option is set just after the first option is created for each attribute / select.

In the case that options were set in url the code for updating defaults was needed to run again to set the values correctly which can be achieved by adding below just outside of the loop:

if (window.location.href.indexOf('#') !== -1) {this._parseQueryParams(window.location.href.substr(window.location.href.indexOf('#') + 1));}

This is placed just after the for loop for options so that it's run just once at the end of the option creation.

So _fillSelect within configurable.js now should look like below:

_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++;
                }
                //new code here - updates the value to first option
                if (i == 0) {
                    this.options.values[attributeId] = options[i].id;
                }   
            }
            //new code here checks 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));}
        }

    },

Original file:

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

Location when overridden in theme:

app/design/frontend/ThemeVendor/Theme/Magento_ConfigurableProduct/web/js/configurable.js

OTHER TIPS

Override vendor\magento\module-swatches\view\frontend\web\js\swatch-renderer.js to your theme
your theme file location will be:
app/design/frontend/Vendor/themename/Magento_Swatches/web/js/swatch-renderer.js

change _RenderControls() function

just wrinte below code at the end of this function

var swatchLength = $('.swatch-attribute').length;
if(swatchLength >= 1){
    if($('.swatch-attribute').hasClass("size")){
        $('.swatch-option').first().trigger('click');
    }
}

http://prntscr.com/n6qo62

I did same thing as jigs suggestion, Thanks jigs But i need to check selected option size first and if no any option was selected then we fire click event on first element.

i follow bellow steps override / copy swatch-renderer.js from

vendor/magento/module-swatches/view/frontend/web/js

To your custom theme

app/design/frontend/{{vendor}}/{{theme}}/Magento_Swatches/web/js

Find _RenderControls: function () and replace

$widget._EmulateSelected($.parseQuery()); $widget._EmulateSelected($widget._getSelectedAttributes());

with

$widget._EmulateSelected($.parseQuery()); $widget._EmulateSelected($widget._getSelectedAttributes());

if($(".swatch-opt .swatch-attribute").find(".selected").length == 0)

$('.swatch-option').first().trigger('click');

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top