Magento2 | PWA | GraphQL

Add category column and filter in an efficient way to the product grid in the Magento 2 admin


In this article, we will check how to add category column and filter in an efficient way (without using objectManager) to the product grid in the Magento 2 admin.

Let's start it by creating custom module.

You can find complete module on Github

Create folder inside app/code/Magelearn/GridColumn

Add registration.php file in it:
<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magelearn_GridColumn', __DIR__);
Add composer.json file in it:
{
    "name": "magelearn/module-gridcolumn",
    "description": "Add Extra column Product's category to the products grid in Magento2 Backend.",
    "type": "magento2-module",
    "license": "OSL-3.0",
    "authors": [
        {
            "email": "info@mage2gen.com",
            "name": "Mage2Gen"
        },
        {
            "email": "vijaymrami@gmail.com",
            "name": "vijay rami"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Magelearn\\GridColumn\\": ""
        }
    }
}
Add etc/module.xml file in it:
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
	<module name="Magelearn_GridColumn" setup_version="1.0.0"/>
</config>
To display new column in product listing grid we will override view/adminhtml/ui_component/product_listing.xml.

Create file product_listing.xml inside view/adminhtml/ui_component folder.
<?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">
    <columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
        <column name="category_id" class="Magelearn\GridColumn\Ui\Component\Listing\Column\Category">
            <argument name="data" xsi:type="array">
            	<item name="options" xsi:type="object">Magelearn\GridColumn\Model\Category\Categorylist</item>
                <item name="config" xsi:type="array">
                	<item name="filter" xsi:type="string">select</item>
                    <item name="add_field" xsi:type="boolean">true</item>
                    <item name="label" xsi:type="string" translate="true">Categories</item>
                    <item name="sortOrder" xsi:type="number">75</item>
                    <item name="dataType" xsi:type="string">select</item>
                </item>
            </argument>
        </column>

    </columns>
</listing>

To Display category name on Product listing grid, we will create our column renderer class.

Create Category.php file inside app/code/Magelearn/GridColumn/Ui/Component/Listing/Column folder.

<?php

namespace Magelearn\GridColumn\Ui\Component\Listing\Column;

use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Framework\View\Element\UiComponent\ContextInterface;

class Category extends \Magento\Ui\Component\Listing\Columns\Column
{
	protected $_productRepository;
	protected $_categoryFactory;
	
	public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        array $components = [],
        array $data = []
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
    	$this->_productRepository = $productRepository;
		$this->_categoryFactory = $categoryFactory;
    }
	
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
        	$fieldName = $this->getData('name');
            foreach ($dataSource['data']['items'] as & $item) {
                $productId = $item['entity_id'];
				$categories = [];
				
                $product = $this->_productRepository->getById($productId);
                $cats = $product->getCategoryIds();
				
                if (count($cats)) {
                    foreach ($cats as $cat) {
						$category = $this->_categoryFactory->create()->load($cat);
                        $categories[] = $category->getName();
                    }
                }
                $item[$fieldName] = implode(',', $categories);
            }
        }
        return $dataSource;
    }
}

If you want to just add new column on the admin product listing grid then add these code files.

Just remove highlighted code from view/adminhtml/ui_component/product_listing.xml file.

Now, let we check to give category filter option.

Create Categorylist.php file inside app/code/Magelearn/GridColumn/Model/Category folder.

<?php

namespace Magelearn\GridColumn\Model\Category;

class CategoryList implements \Magento\Framework\Option\ArrayInterface
{
    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $collectionFactory
    ) {
        $this->_categoryCollectionFactory = $collectionFactory;

    }
    public function toOptionArray($addEmpty = true)
    {

        $collection = $this->_categoryCollectionFactory->create()
        			->addAttributeToSelect('name')//->addRootLevelFilter()->load();
        			->addAttributeToFilter('level', ['gt' => 1]) //remove root category 
                	->addAttributeToFilter('is_active', ['gt' => 0]); //for active categories
        $options = [];
        if ($addEmpty) {
            $options[] = ['label' => __('-- Please Select a Category --'), 'value' => ''];
        }
        foreach ($collection as $category) {
            $options[] = ['label' => $category->getName(), 'value' => $category->getId()];
        }
        return $options;
    }
}

Now, to display result properly after filter, need to modify default DataProvider for ProductDataProvider.

For that first create di.xml file inside app/code/Magelearn/GridColumn/etc folder.

<?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\Catalog\Ui\DataProvider\Product\ProductDataProvider" type="Magelearn\GridColumn\Ui\DataProvider\Product\ProductDataProvider" />
</config>

Now create ProductDataProvider.php file inside app/code/Magelearn/GridColumn/Ui/DataProvider/Product/ folder.

<?php

namespace Magelearn\GridColumn\Ui\DataProvider\Product;

class ProductDataProvider extends \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider
{
    public function addFilter(\Magento\Framework\Api\Filter $filter)
    {
        if ($filter->getField() == 'category_id') {
            $this->getCollection()->addCategoriesFilter(array('in' => $filter->getValue()));
        } elseif (isset($this->addFilterStrategies[$filter->getField()])) {
            $this->addFilterStrategies[$filter->getField()]
                ->addFilter(
                    $this->getCollection(),
                    $filter->getField(),
                    [$filter->getConditionType() => $filter->getValue()]
                );
        } else {
            parent::addFilter($filter);
        }
    }
}

After adding above files, just run Magento commands:

php bin/magento set:upg

php bin/magento set:d:c

php bin/magento set:s:d -f en_US

php bin/magento c:c

php bin/magento c:f

Now, you can see New column "Categories" will be added in product listing grid and also filter with active categories list be added.

0 Comments On "Add category column and filter in an efficient way to the product grid in the Magento 2 admin"

Back To Top