0

I display out-of-Stock in my configurable products. But it is selectable, I like to set as not selectable option for only out of stock. Please let me know.

enter image description here

0
+50

You need to send product's stock status into jsConfig using plugin

app/code/Vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable">
        <plugin name="vendor_configurable_product_configurable"
                type="Vendor\Module\Plugin\Configurable"
                sortOrder="1"/>
    </type>
</config>

app/code/Vendor/Module/Plugin/Configurable.php

<?php

namespace Vendor\Module\Plugin;

use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Json\DecoderInterface;
use Magento\CatalogInventory\Api\StockRegistryInterface;

class Configurable
{

    protected $jsonEncoder;
    protected $jsonDecoder;
    protected $stockRegistry;

    public function __construct(
        EncoderInterface $jsonEncoder,
        DecoderInterface $jsonDecoder,
        StockRegistryInterface $stockRegistry
    ) {

        $this->jsonDecoder = $jsonDecoder;
        $this->jsonEncoder = $jsonEncoder;
        $this->stockRegistry = $stockRegistry;
    }

    public function aroundGetJsonConfig(
        \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject,
        \Closure $proceed
    )
    {
        $status = [];
        $config = $proceed();
        $config = $this->jsonDecoder->decode($config);

        foreach ($subject->getAllowProducts() as $product) {
            $stockitem = $this->stockRegistry->getStockItem(
                $product->getId(),
                $product->getStore()->getWebsiteId()
            );
            $status[$product->getId()] = $stockitem->getIsInStock();
        }

        $config['status'] = $status;

        return $this->jsonEncoder->encode($config);
    }
}

Override swatch-renderer.js from

vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js

to

app/design/frontend/Vendor/Theme/Magento_Swatches/web/js/swatch-renderer.js

And change _RenderSwatchOptions function with below code

_RenderSwatchOptions: function (config, controlId) {
    var optionConfig = this.options.jsonSwatchConfig[config.id],
        optionClass = this.options.classes.optionClass,
        moreLimit = parseInt(this.options.numberToShow, 10),
        moreClass = this.options.classes.moreButton,
        moreText = this.options.moreButtonText,
        countAttributes = 0,
        html = '',
        $widget = this;//Added custom code

    if (!this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {
        return '';
    }

    $.each(config.options, function () {
        var id,
            type,
            value,
            thumb,
            label,
            attr;

        if (!optionConfig.hasOwnProperty(this.id)) {
            return '';
        }

        // Add more button
        if (moreLimit === countAttributes++) {
            html += '<a href="#" class="' + moreClass + '">' + moreText + '</a>';
        }

        id = this.id;
        type = parseInt(optionConfig[id].type, 10);
        value = optionConfig[id].hasOwnProperty('value') ? optionConfig[id].value : '';
        thumb = optionConfig[id].hasOwnProperty('thumb') ? optionConfig[id].thumb : '';
        label = this.label ? this.label : '';
        attr =
            ' id="' + controlId + '-item-' + id + '"' +
            ' aria-checked="false"' +
            ' aria-describedby="' + controlId + '"' +
            ' tabindex="0"' +
            ' option-type="' + type + '"' +
            ' option-id="' + id + '"' +
            ' option-label="' + label + '"' +
            ' aria-label="' + label + '"' +
            ' option-tooltip-thumb="' + thumb + '"' +
            ' option-tooltip-value="' + value + '"' +
            ' role="option"';

        if (!this.hasOwnProperty('products') || this.products.length <= 0) {
            attr += ' option-empty="true"';
        }

        /*Added custom code*/
        var disabledStyle = '';
        if(!$widget.options.jsonConfig.status[this.products[0]]){
            disabledStyle = 'pointer-events: none; cursor:not-allowed;';
        }

        if (type === 0) {
            // Text
            html += '<div class="' + optionClass + ' text" ' + attr + '>' + (value ? value : label) +
                '</div>';
        } else if (type === 1) {
            // Color
            html += '<div class="' + optionClass + ' color" ' + attr +
                ' style="background: ' + value +
                ' no-repeat center; background-size: initial;'+disabledStyle+'" >' + '' +
                '</div>';//Added custom code
        } else if (type === 2) {
            // Image
            html += '<div class="' + optionClass + ' image" ' + attr +
                ' style="background: url(' + value + ') no-repeat center; background-size: initial;">' + '' +
                '</div>';
        } else if (type === 3) {
            // Clear
            html += '<div class="' + optionClass + '" ' + attr + '></div>';
        } else {
            // Default
            html += '<div class="' + optionClass + '" ' + attr + '>' + label + '</div>';
        }
    });

    return html;
},

This will only works for text swatches and color swatches.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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