Question

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.

Was it helpful?

Solution

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

OTHER TIPS

@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;
 }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top