How to add a custom columns to the Magento 2 products grid

It’s easy to add a column to the products grid if a value that you want to display in the column is a product attribute. They are already present in the products grid toolbar under Columns control. You just check/uncheck columns that you want to be displayed or removed from the grid. But what if you want to display values like quantity and website that aren’t product attribute? If you continue to read you will learn how to add values like this to the products grid.

Introduction

Because stock management can be turned on/off per product, we will add a new column to the products grid that will display if stock management is turned on or off.
For all of the code examples, I created a Magento 2 module, named Inchoo_Custom.

If you want to learn how to create a Magento 2 module, you can check this: How to create a basic module in Magento 2

It’s important that Magento’s Magento_Catalog module is loaded before our module, that’s why we will add it under sequence tag in the module.xml file.

app/code/Inchoo/Custom/etc/module.xml

<?xml version="1.0" encoding="utf-8" ?>
<config xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Inchoo_Custom" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

After editing module.xml we need to update app/etc/config.php file with console command:

php bin/magento setup:upgrade

Product listing UI component instance

To render products grid Magento 2 uses Listing UI component instance named product_listing and XML configuration file for it is Magento_Catalog/view/adminhtml/ui_component/product_listing.xml. If we want to customize it we need to create a file in our module with the same path and name.

app/code/Inchoo/Custom/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"> 
    <columns name="product_columns"> 
        <column name="manage_stock" component="Magento_Ui/js/grid/columns/select" sortOrder="76"> 
            <settings> 
                <addField>true</addField> 
                <options class="MagentoConfigModelConfigSourceYesno"/> 
                <filter>select</filter> 
                <dataType>select</dataType> 
                <sortable>false</sortable> 
                <label translate="true">Manage Stock</label> 
            </settings> 
        </column> 
    </columns> 
</listing>

To add new column we need to reference columns UI component named product_columns from the original config file and add our new column to it. We named our column manage_stock with label Manage Stock.

Run this console command to clean cache:

php bin/magento cache:clean config

After we clean cache we should see our new column in the products grid but data is missing. This is because we didn’t add stock management data to products collection.

Product listing data provider

Best location to add stock management data to products collection is in data provider class used by product_listing UI component instance.

Magento_Catalog/view/adminhtml/ui_component/product_listing.xml

<dataSource name="product_listing_data_source" component="Magento_Ui/js/grid/provider"> 
    <settings> 
        <storageConfig> 
            <param name="dataScope" xsi_type="string">filters.store_id</param> 
        </storageConfig> 
        <updateUrl path="mui/index/render"/> 
    </settings> 
    <aclResource>Magento_Catalog::products</aclResource> 
    <dataProvider class="MagentoCatalogUiDataProviderProductProductDataProvider" name="product_listing_data_source"> 
        <settings> 
            <requestFieldName>id</requestFieldName> 
            <primaryFieldName>entity_id</primaryFieldName> 
        </settings> 
    </dataProvider> 
</dataSource>

If we look at the dataSource UI component we will see that the dataProvider class is MagentoCatalogUiDataProviderProductProductDataProvider.

If we look at this data provider class, we will see two properties addFieldStrategies and addFilterStrategies. Both of them are arrays with additional strategies we can do on a collection for a specific column (field). They are respectively called in data provider’s addField and addFilter methods. We will create own strategies for our stock management column.

Manage stock field strategy

First, we will create a field strategy that will add stock management status to the products collection.

InchooCustomUiDataProviderProductAddManageStockFieldToCollection

<?php 
namespace InchooCustomUiDataProviderProduct; 
class AddManageStockFieldToCollection implements MagentoUiDataProviderAddFieldToCollectionInterface 
{ 
    public function addField(MagentoFrameworkDataCollection $collection, $field, $alias = null) 
    { 
        $collection->joinField('manage_stock', 'cataloginventory_stock_item', 'manage_stock', 'product_id=entity_id', null, 'left'); 
    } 
}

In AddManageStockFieldToCollection field strategy we implemented addField method from MagentoUiDataProviderAddFieldToCollectionInterface interface. Stock management status comes from the manage_stock column in cataloginventory_stock_item DB table. We used this information and MagentoEavModelEntityCollectionAbstractCollection::joinField method to add Stock management status to product collection.

Manage stock filter strategy

For times when someone wants to filter grid data by stock management status, we need to create this filtering strategy.

InchooCustomUiDataProviderProductAddManageStockFilterToCollection

<?php 
namespace InchooCustomUiDataProviderProduct; 
class AddManageStockFilterToCollection implements MagentoUiDataProviderAddFilterToCollectionInterface 
{ 
    public function addFilter(MagentoFrameworkDataCollection $collection, $field, $condition = null) 
    { 
        if (isset($condition['eq'])) { 
            $collection->addFieldToFilter($field, $condition); 
        } 
    } 
}

In AddManageStockFilterToCollection filter strategy we implemented addFilter method from MagentoUiDataProviderAddFilterToCollectionInterface. If grid is filterd by stock management status we will forward filter condtition to MagentoEavModelEntityCollectionAbstractCollection::addFieldToFilter method.

Add strategies to the product listing data provider

If we want to use just created strategies we need to add them to the product_listing data provider. We will do that in the di.xml file.

app/code/Inchoo/Custom/etc/adminhtml/di.xml

<?xml version="1.0" encoding="utf-8" ?> 
<config xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> 
    <type name="MagentoCatalogUiDataProviderProductProductDataProvider"> 
        <arguments> 
            <argument name="addFieldStrategies" xsi_type="array"> 
                <item name="manage_stock" xsi_type="object">InchooCustomUiDataProviderProductAddManageStockFieldToCollection</item> 
            </argument> 
            <argument name="addFilterStrategies" xsi_type="array"> 
                <item name="manage_stock" xsi_type="object">InchooCustomUiDataProviderProductAddManageStockFilterToCollection</item> 
            </argument> 
        </arguments> 
    </type> 
</config>

Run this console command to clean cache:

php bin/magento cache:clean config

After we clean cache we should see our new column in the products grid with data in it.