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.