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="Magento\Config\Model\Config\Source\Yesno"/>
<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="Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider" 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 Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider.
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.
Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFieldToCollection
<?php
namespace Inchoo\Custom\Ui\DataProvider\Product;
class AddManageStockFieldToCollection implements \Magento\Ui\DataProvider\AddFieldToCollectionInterface
{
public function addField(\Magento\Framework\Data\Collection $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 Magento\Ui\DataProvider\AddFieldToCollectionInterface interface. Stock management status comes from the manage_stock column in cataloginventory_stock_item DB table. We used this information and Magento\Eav\Model\Entity\Collection\AbstractCollection::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.
Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFilterToCollection
<?php
namespace Inchoo\Custom\Ui\DataProvider\Product;
class AddManageStockFilterToCollection implements \Magento\Ui\DataProvider\AddFilterToCollectionInterface
{
public function addFilter(\Magento\Framework\Data\Collection $collection, $field, $condition = null)
{
if (isset($condition['eq'])) {
$collection->addFieldToFilter($field, $condition);
}
}
}
In AddManageStockFilterToCollection filter strategy we implemented addFilter method from Magento\Ui\DataProvider\AddFilterToCollectionInterface. If grid is filterd by stock management status we will forward filter condtition to Magento\Eav\Model\Entity\Collection\AbstractCollection::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="Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider">
<arguments>
<argument name="addFieldStrategies" xsi:type="array">
<item name="manage_stock" xsi:type="object">Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFieldToCollection</item>
</argument>
<argument name="addFilterStrategies" xsi:type="array">
<item name="manage_stock" xsi:type="object">Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFilterToCollection</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.
6 comments
hi,
how we can add this column in Product export csv?
Use “php bin/magento cache:clean config” instead of “php bin/magneto cache:clean config”
It’s fixed. Thank you
Please fix syntax error
showing source of this file
app/code/Inchoo/Custom/etc/module.xml
second line. there are no closing “>”
It’s fixed. Thank you
Hi
I am trying to add custom input box with
with above.$this->addColumn(
'product_custom_name[]',
[
'filter' => false,
'sortable' => false,
'header' => __('Custom Name'),
'renderer' => \Test\Series\Block\Adminhtml\Product\Grid\Renderer\CustomName::class,
'name' => 'product_custom_name[]',
'inline_css' => 'product_custom_name',
'type' => 'input',
'index' => 'name'
]
);
How can we pass productis in array because when m posting this its very diffuclt to get which custom name is for which product