How to display configurable product swatches when product is Out of stock
-
14-04-2021 - |
Frage
I have a configurable products with few sizes, let's say : 123, 160, M, S, L, XL
When I put products M and S on qty 0, which means it is out of stock
, then sizes disappear form the swatches option.
I was expected to see also out of stock products with a special class and to be non clickable, but out of stock products disappear.
I found a solution and I will post my answer. Maybe that will help someone.
Lösung
To solve this issue:
Step 1
I installed this module( for some other versions of magento maybe this will work without step 2)
https://github.com/mjankiewicz/MagentoConfigurableProduct
Step 2
Create a module with:
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">
<preference for="Magento\Swatches\Block\Product\Renderer\Configurable" type="Vendor\Namespace\Block\Outstock" />
</config>
then create Block/Outstock.php
<?php
namespace vendor\namespace\Block;
class Outstock extends \Magento\Swatches\Block\Product\Renderer\Configurable
{
public function getAllowProducts()
{
if (!$this->hasAllowProducts()){
$skipSaleableCheck = 1;
$products = $skipSaleableCheck ?
$this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
$this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
}
After this run
php bin/magento setup:upgrade
php bin/magento cache:clean
php bin/magento cache:flush
Of course that you can combine those 2 modules. You can take /Helper/Data.php
form the first module JanSoft_ConfigurableProduct and put this into the second module, or the oposite.
Andere Tipps
You can also override the plugin to display the swatches as well as dropdown option if product is out of stock.
1)etc/di/xml.
<type name="Magento\ConfigurableProduct\Plugin\Model\ResourceModel\Attribute\InStockOptionSelectBuilder">
<plugin name="Magento_ConfigurableProduct_Plugin_Model_ResourceModel_InStockOptionSelectBuilder"
type="Vendor\Mymodule\Plugin\Attribute\InStockOptionSelector"/>
</type>
2)Plugin\Attribute
namespace Vendor\Mymodule\Plugin\Attribute;
use Magento\CatalogInventory\Model\ResourceModel\Stock\Status;
use Magento\ConfigurableProduct\Model\ResourceModel\Attribute\OptionSelectBuilderInterface;
use Magento\Framework\DB\Select;
class InStockOptionSelector extends \Magento\ConfigurableProduct\Plugin\Model\ResourceModel\Attribute\InStockOptionSelectBuilder
{
private $stockStatusResource;
public function __construct(Status $stockStatusResource)
{
parent::__construct($stockStatusResource);
}
/**
* @param OptionSelectBuilderInterface $subject
* @param Select $select
* @return Select
*/
public function afterGetSelect(OptionSelectBuilderInterface $subject, Select $select)
{
return $select;
}
}
3) override block in di.xml
<preference for="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable" type="Vendor\Mymodule\Block\Product\View\Type\Configurable"/>
4)Configurable.php
namespace Vendor\Mymodule\Block\Product\View\Type;
use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Customer\Model\Session;
use Magento\Framework\Locale\Format;
use Magento\Framework\Pricing\PriceCurrencyInterface;
class Configurable extends \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable
{
public function __construct(\Magento\Catalog\Block\Product\Context $context, \Magento\Framework\Stdlib\ArrayUtils $arrayUtils, \Magento\Framework\Json\EncoderInterface $jsonEncoder, \Magento\ConfigurableProduct\Helper\Data $helper, \Magento\Catalog\Helper\Product $catalogProduct, CurrentCustomer $currentCustomer, PriceCurrencyInterface $priceCurrency, ConfigurableAttributeData $configurableAttributeData, array $data = [], $localeFormat = null, $customerSession = null)
{
parent::__construct($context, $arrayUtils, $jsonEncoder, $helper, $catalogProduct, $currentCustomer, $priceCurrency, $configurableAttributeData, $data, $localeFormat, $customerSession);
}
public function getAllowProducts()
{
if (!$this->hasAllowProducts()) {
$products = [];
$skipSaleableCheck = $this->catalogProduct->getSkipSaleableCheck();
$allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null);
foreach ($allProducts as $product) {
if ($product->isSaleable() || $skipSaleableCheck == 1) {
$products[] = $product;
}
}
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
}
Hope so it will help .
Add into di.xml
<type name="Magento\ConfigurableProduct\Model\Product\Type\Configurable">
<plugin name="Vendor_Module::disable-stock-filter" type="Vendor\Module\Plugins\ConfigurableProduct\Model\Product\Type\Configurable"/>
</type>
create file Configurable.php
namespace Vendor\Module\Plugins\ConfigurableProduct\Model\Product\Type;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as NativeConfigurable;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection;
class Configurable
{
public function afterGetUsedProductCollection(NativeConfigurable $subject, $collection)
{
$collection->setFlag('has_stock_status_filter', true);
return $collection;
}
}