0

In admin, I want to add column of category and also add category filter in product grid.

How to do this?

Please help me.

Thanks.

  • Can you add a bit more detail? Are you referencing the layered navigation that magento offers? I'm not sure what you mean by 'column of category'. Here are the docs for layered navigation: docs.magento.com/m2/ee/user_guide/catalog/… – mlunt Apr 23 at 17:48
1

To add category column in product grid, add this below code in your product_listing.xml file :

<?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="category_id" provider="${ $.parentName }" component="Magento_Ui/js/form/element/ui-select" template="ui/grid/filters/elements/ui-select">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="filterOptions" xsi:type="boolean">true</item>
                        <item name="levelsVisibility" xsi:type="number">1</item>
                    </item>
                </argument>
                <settings>
                    <options class="\Vendor\Module\Model\Category\CategoryList"/>
                    <caption translate="true">– Please Select a Category –</caption>
                    <label translate="true">Categories</label>
                    <dataScope>category_id</dataScope>
                    <imports>
                        <link name="visible">componentType = column, index = ${ $.index }:visible</link>
                    </imports>
                </settings>
            </filterSelect>
        </filters>
    </listingToolbar>
    <columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
        <column name="category_id" class="Vendor\Module\Ui\Component\Listing\Column\Category">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Categories</item>
                    <item name="sortOrder" xsi:type="number">35</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

Now, we need to override prepareDataSource() method. To get category values in the prepareDataSource() method like below code :

Vendor\Module\Ui\Component\Listing\Column\Category.php

<?php

namespace Vendor\Module\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
{

    /**
     * @var \Magento\Catalog\Model\ProductFactory
     */
    private $productFactory;

    /**
     * @var \Magento\Catalog\Model\CategoryFactory
     */
    private $categoryFactory;

    /**
     * [__construct description]
     * @param ContextInterface                       $context            [description]
     * @param UiComponentFactory                     $uiComponentFactory [description]
     * @param array                                  $components         [description]
     * @param array                                  $data               [description]
     * @param \Magento\Catalog\Model\ProductFactory  $productFactory     [description]
     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory    [description]
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        array $components = [],
        array $data = [],
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
        $this->productFactory = $productFactory;
        $this->categoryFactory = $categoryFactory;
    }

    /**
     * Prepare date for category column
     * @param  array  $dataSource [description]
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        $fieldName = $this->getData('name');
        if (isset($dataSource['data']['items'])) {
            foreach ($dataSource['data']['items'] as &$item) {
                $productId = $item['entity_id'];
                $product = $this->productFactory->create()->load($productId);
                $categoryIds = $product->getCategoryIds();
                $categories = [];
                if (count($categoryIds)) {
                    foreach ($categoryIds as $categoryId) {
                        $categoryData = $this->categoryFactory->create()->load($categoryId);
                        $categories[] = $categoryData->getName();
                    }
                }
                $item[$fieldName] = implode(',', $categories);
            }
        }
        return $dataSource;
    }
}

create di.xml file for override class :

<?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="Vendor\Module\Ui\DataProvider\Product\ProductDataProvider" />
</config>

Now, add method addFilter() to Vendor\Module\Ui\DataProvider\Product\ProductDataProvider.php

<?php

namespace Vendor\Module\Ui\DataProvider\Product;

class ProductDataProvider extends \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider
{
    /**
     * For filter grid according to category
     * @param \Magento\Framework\Api\Filter $filter
     */
    public function addFilter(\Magento\Framework\Api\Filter $filter)
    {
        if ($filter->getField() == 'category_id') {
            $this->getCollection()->addCategoriesFilter(['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);
        }
    }
}

And last to add Options to the category filter dropdown :

Vendor\Module\Model\Category\CategoryList.php

<?php

namespace Vendor\Module\Model\Category;

use Magento\Catalog\Model\Category as CategoryModel;

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

    /**
     * @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory
     */
    private $categoryCollectionFactory;
    /**
     * [__construct description]
     * @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $collectionFactory [description]
     */
    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $collectionFactory
    ) {
        $this->categoryCollectionFactory = $collectionFactory;
    }

    /**
     * Get list of categories
     * @return array
     */
    public function toOptionArray()
    {
        $collection = $this->categoryCollectionFactory->create();
        $collection->addAttributeToSelect(['name', 'is_active', 'parent_id']);
        $categoryById = [
            CategoryModel::TREE_ROOT_ID => [
                'value' => CategoryModel::TREE_ROOT_ID,
                'optgroup' => null,
            ],
        ];
        foreach ($collection as $category) {
            foreach ([$category->getId(), $category->getParentId()] as $categoryId) {
                if (!isset($categoryById[$categoryId])) {
                    $categoryById[$categoryId] = ['value' => $categoryId];
                }
            }

            $categoryById[$category->getId()]['is_active'] = $category->getIsActive();
            $categoryById[$category->getId()]['label'] = $category->getName();
            $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()];
        }

        return $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup'];
    }
}

Hope, It will helpful for you.

  • 1
    Thanks man ..!!! It's working :) – Niket Apr 24 at 2:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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