When change a swatch option how to get a selected simple product in category product listing page in magento 2

Create plugin to add quantity to the JS config to get from swatch renderer

Vendor/Module/etc/frontend/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\Block\ConfigurableProduct\Product\View\Type\Configurable"
                sortOrder="1"/>
    </type>
</config>

Create a plugin file with quantity script below in vendor\module\Plugin\Block\ConfigurableProduct\Product\View\Type\Configurable.php

<?php

namespace vendor\module\Plugin\Block\ConfigurableProduct\Product\View\Type;

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;
    }

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

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

        $config['quantities'] = $quantities;

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

And your phtml looks like

<span class="classname"><?php echo $_product->getId(); ?></span>

You can get product quantity from swatches you need to override vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js function _Rebuild add following code..

 //Check weather product list page or view page
    if ($('body.catalog-product-view').size() <= 0) {
        if( controls.size() == selected.size()){
            var productQty = $widget.options.jsonConfig.quantities[this.getProduct()];
            $widget.element.parents('.product-item-info').find('.classname').html(productQty);
        }
    }

finally it looks like

       _Rebuild: function () {
            var $widget = this,
                controls = $widget.element.find('.' + $widget.options.classes.attributeClass + '[attribute-id]'),
                selected = controls.filter('[option-selected]');

            // Enable all options
            $widget._Rewind(controls);

            // done if nothing selected
            if (selected.size() <= 0) {
                return;
            }

    //Check weather product list page or view page
    if ($('body.catalog-product-view').size() <= 0) {
        if( controls.size() == selected.size()){
            var productQty = $widget.options.jsonConfig.quantities[this.getProduct()];
            $widget.element.parents('.product-item-info').find('.classname').html(productQty);
        }
    }

            // Disable not available options
            controls.each(function () {
                var $this = $(this),
                    id = $this.attr('attribute-id'),
                    products = $widget._CalcProducts(id);

                if (selected.size() === 1 && selected.first().attr('attribute-id') === id) {
                    return;
                }

                $this.find('[option-id]').each(function () {
                    var $element = $(this),
                        option = $element.attr('option-id');

                    if (!$widget.optionsMap.hasOwnProperty(id) || !$widget.optionsMap[id].hasOwnProperty(option) ||
                        $element.hasClass('selected') ||
                        $element.is(':selected')) {
                        return;
                    }

                    if (_.intersection(products, $widget.optionsMap[id][option].products).length <= 0) {
                        $element.attr('disabled', true).addClass('disabled');
                    }
                });
            });
        },

You can add your logic here instead of adding scripts in phtml files.

To override js file copy from vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js to app/design/VENDOR/THEME/Magento_Swatches/web/js/swatch-renderer.js Run upgrade and content deploy to see changes


You can find prodcutId from [Magento_Root]\vendor\magento\module-swatches\view\frontend\web\js\swatch-renderer.js

find _OnClick function.

_OnClick: function ($this, $widget) {
        var $parent = $this.parents('.' + $widget.options.classes.attributeClass),
            $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass),
            attributeId = $parent.attr('attribute-id'),
            $input = $parent.find('.' + $widget.options.classes.attributeInput);

        if ($widget.inProductList) {
            $input = $widget.productForm.find(
                '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]'
            );
        }

        if ($this.hasClass('disabled')) {
            return;
        }

        if ($this.hasClass('selected')) {
            $parent.removeAttr('option-selected').find('.selected').removeClass('selected');
            $input.val('');
            $label.text('');
        } else {
            $parent.attr('option-selected', $this.attr('option-id')).find('.selected').removeClass('selected');
            $label.text($this.attr('option-label'));
            $input.val($this.attr('option-id'));
            $this.addClass('selected');
            console.log($this.attr('option-id')); // Here you can find selected simple product id
        }

        $widget._Rebuild();

        if ($widget.element.parents($widget.options.selectorProduct)
                .find(this.options.selectorProductPrice).is(':data(mage-priceBox)')
        ) {
            $widget._UpdatePrice();
        }

        $widget._LoadProductMedia();
        $input.trigger('change');
    },

It will help you.