2

I want to add product stock status field in product grid and in filter options. How can I achieve this? enter image description here

I am using Magento CE 2.1.4.

2 Answers 2

7

Try following way:

For M 2.2 SR/Stackexchange/view/adminhtml/ui_component/product_listing.xml


<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <listingToolbar name="listing_top">
        <filters name="listing_filters">
            <filterSelect name="stock_status" provider="${ $.parentName }">
                <settings>
                    <options class="SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus\Options"/>
                    <label translate="true">Stock Status</label>
                    <dataScope>stock_status</dataScope>
                </settings>
            </filterSelect>
        </filters>
    </listingToolbar>
    <columns name="product_columns">
        <column name="stock_status" class="SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus" sortOrder="900">
            <settings>
                <addField>true</addField>
                <filter>select</filter>
                <options class="SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus\Options"/>
                <label translate="true">Stock Status</label>
                <dataType>select</dataType>
            </settings>
        </column>
    </columns>
</listing>

For M 2.1 < SR/Stackexchange/view/adminhtml/ui_component/product_listing.xml


<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <listingToolbar name="listing_top">
        <filters name="listing_filters">
            <filterSelect name="stock_status" provider="${ $.parentName }">
                <argument name="optionsProvider" xsi:type="configurableObject">
                    <argument name="class" xsi:type="string">SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus\Options</argument>
                </argument>
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="provider" xsi:type="string">${ $.parentName }</item>
                        <item name="dataScope" xsi:type="string">stock_status</item>
                        <item name="label" xsi:type="string" translate="true">Stock Status</item>
                    </item>
                </argument>
            </filterSelect>
        </filters>
    </listingToolbar>
    <columns name="product_columns">
        <column name="stock_status">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus\Options</item>
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">select</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
                    <item name="add_field" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">select</item>
                    <item name="label" xsi:type="string" translate="true">Stock Status</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

SR/Stackexchange/Ui/Component/Listing/Columns/StockStatus/Options.php


namespace SR\Stackexchange\Ui\Component\Listing\Columns\StockStatus;

use Magento\Framework\Data\OptionSourceInterface;

class Options implements OptionSourceInterface
{
    /**
     * @var array
     */
    protected $options;

    /**
     * Get options
     *
     * @return array
     */
    public function toOptionArray()
    {
        if ($this->options !== null) {
            return $this->options;
        }

        $this->options = [
            [
                'label' => __('In Stock'),
                'value' => 1
            ],
            [
                'label' => __('Out of Stock'),
                'value' => 0
            ]
        ];

        return $this->options;
    }
}

SR/Stackexchange/Ui/Component/Listing/Columns/StockStatus.php


namespace SR\Stackexchange\Ui\Component\Listing\Columns;

class StockStatus extends \Magento\Ui\Component\Listing\Columns\Column
{
    /**
     * Column name
     */
    const NAME = 'column.stock_status';

    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
            $fieldName = $this->getData('name');
            foreach ($dataSource['data']['items'] as & $item) {
                if (isset($item[$fieldName])) {
                    $item[$fieldName] = $this->getStatus($item[$fieldName]);
                }
            }
        }

        return $dataSource;
    }

    /**
     * @param $status
     * @return \Magento\Framework\Phrase
     */
    private function getStatus($status)
    {
        if($status == 1) {
            return __('In Stock');
        } else {
            return __('Out of Stock');
        }
    }
}

SR/Stackexchange/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\Catalog\Ui\DataProvider\Product\ProductDataProvider">
        <plugin name="join_product_grid_with_stock_status" type="SR\Stackexchange\Plugin\Ui\DataProvider\Product\ProductDataProvider" sortOrder="100" />
    </type>
</config>

SR/Stackexchange/Plugin/Ui/DataProvider/Product/ProductDataProvider.php


namespace SR\Stackexchange\Plugin\Ui\DataProvider\Product;

class ProductDataProvider
{
    /**
     * @param \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider $subject
     * @param \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection $collection
     * @return mixed
     */
    public function afterGetCollection(
        \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider $subject,
        $collection
    ) {
        $columns = $collection->getSelect()->getPart(\Zend_Db_Select::COLUMNS);
        if (!$collection->isLoaded() && !$this->checkJoin($columns)) {
            $collection->joinTable(
                'cataloginventory_stock_status',
                'product_id=entity_id',
                ["stock_status" => "stock_status"],
                null ,
                'left'
            )->addAttributeToSelect('stock_status');
        }

        return $collection;
    }

    /**
     * @param array $columns
     * @return bool
     */
    private function checkJoin($columns)
    {
        foreach ($columns as $column) {
            if(is_array($column)) {
                if(in_array('stock_status', $column)) {
                    return true;
                }
            }
        }

        return false;
    }
}
9
  • Hello @sohel i am getting error The requested component ("settings") is not found. </settings> Jun 8, 2018 at 12:06
  • :) ok. it's m2.2.4. Can you convert this xml? only SR/Stackexchange/view/adminhtml/ui_component/product_listing.xml?
    – Sohel Rana
    Jun 8, 2018 at 12:08
  • yes, till now SR/Stackexchange/view/adminhtml/ui_component/product_listing.xml . Jun 8, 2018 at 12:21
  • Thanks a lot, I have modified your code for Magento 2.1.4 and it is working now. Jun 8, 2018 at 12:36
  • 1
    Hey, good. I have updated too. check updated answer.
    – Sohel Rana
    Jun 8, 2018 at 12:41
0

@sohel answer is perfect for magetno 2.2, i have updated some code for Magento 2.1.

Vendor/Module/view/adminhtml/ui_component/product_listing.xml

<?xml version="1.0"?>

<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
 <listingToolbar name="listing_top">
    <filters name="listing_filters">
         <filterSelect name="stock_status">
            <argument name="optionsProvider" xsi:type="configurableObject">
                <argument name="class" xsi:type="string">Vendor\Module\Model\Product\Stock\Status</argument>
            </argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="provider" xsi:type="string">${ $.parentName }</item>
                    <item name="dataScope" xsi:type="string">stock_status</item>
                    <item name="caption" xsi:type="string" translate="true">All Store Views</item>
                    <item name="label" xsi:type="string" translate="true">Store View</item>
                </item>
            </argument>
        </filterSelect>
    </filters>
</listingToolbar>
<columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
   <column name="stock_status" class="Vendor\Module\Ui\Component\Listing\Column\InStock">
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="object">Vendor\Module\Model\Product\Stock\Status</item>
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">select</item>
                <item name="sortOrder" xsi:type="number">60</item>
                <item name="dataType" xsi:type="string">select</item>
                <item name="label" translate="true" xsi:type="string">Stock Status</item>
            </item>
        </argument>
    </column>
</columns>
</listing>

Vendor/Module/Model/Product/Stock/Status.php

 <?php

 namespace Vendor\Module\Model\Product\Stock;

 class Status implements \Magento\Framework\Option\ArrayInterface
 {


   public function toOptionArray() {
    return [
        ['value' => 0, 'label' => __('Out of Stock')],
        ['value' => 1, 'label' => __('In Stock')]
    ];
   }
}

Vendor/Module/Ui/Component/Listing/Column/InStock.php

<?php

namespace Vendor\Module\Ui\Component\Listing\Column;

class InStock extends \Magento\Ui\Component\Listing\Columns\Column
{

 /**
  * Column name
  */
 const NAME = 'column.stock_status';

 /**
  * Prepare Data Source
  *
  * @param array $dataSource
  * @return array
  */
 public function prepareDataSource(array $dataSource)
 {
    if (isset($dataSource['data']['items'])) {
        $fieldName = $this->getData('name');
        foreach ($dataSource['data']['items'] as & $item) {
            if (isset($item[$fieldName])) {
                $item[$fieldName] = $this->getStatus($item[$fieldName]);
            }
        }
    }

    return $dataSource;
 }

 /**
  * @param $status
  * @return \Magento\Framework\Phrase
  */
  private function getStatus($status)
  {
    if($status == 1) {
        return __('In Stock');
    } else {
        return __('Out of Stock');
    }
  }
}

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\Catalog\Ui\DataProvider\Product\ProductDataProvider">
    <plugin name="join_product_grid_with_stock_status" type="Vendor\Module\Plugin\Ui\DataProvider\Product\ProductDataProvider" sortOrder="100" />
  </type>
</config>

Vendor/Module/Plugin/Ui/DataProvider/Product/ProductDataProvider.php

<?php

namespace Vendor\Module\Plugin\Ui\DataProvider\Product;

class ProductDataProvider
{
/**
 * @param \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider $subject
 * @param \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection $collection
 * @return mixed
 */
 public function afterGetCollection(
    \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider $subject,
    $collection
 ) {
    $columns = $collection->getSelect()->getPart(\Zend_Db_Select::COLUMNS);
    if (!$collection->isLoaded() && !$this->checkJoin($columns)) {
        $collection->joinTable(
            'cataloginventory_stock_status',
            'product_id=entity_id',
            ["stock_status" => "stock_status"],
            null ,
            'left'
        )->addAttributeToSelect('stock_status');
    }

    return $collection;
 }

 /**
  * @param array $columns
  * @return bool
  */
 private function checkJoin($columns)
 {
    foreach ($columns as $column) {
        if(is_array($column)) {
            if(in_array('stock_status', $column)) {
                return true;
            }
        }
    }

    return false;
 }
}
1
  • Did your code support magento 2.3.4?
    – zus
    Sep 23, 2020 at 2:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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