Magento2 | PWA | GraphQL

Provide Category Product Edit Link and Category Product Thumbnail Image at Admin for Magento 2


In this post we will check how to Add Category Product Edit Link and Display Category Products thumbnail image at Admin for Magento 2 Category Products Grid.

You can find complete module on Github at Magelearn_CategoryProductEdit

Let's start it by creating custom module.


Create folder inside app/code/Magelearn/CategoryProductEdit

Add registration.php file in it:

<?php

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'Magelearn_CategoryProductEdit',
    __DIR__
);

Add composer.json file in it:

{
    "name": "magelearn/module-category-product-edit",
    "description": "Provide Category Product Edit Link at Admin for Magento 2",
    "type": "magento2-module",
    "require": {},
    "authors": [
        {
            "name": "vijay rami",
            "email": "vijaymrami@gmail.com"
        }
    ],
    "license": "proprietary",
    "minimum-stability": "dev",
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Magelearn\\CategoryProductEdit\\": ""
        }
    }
}

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_CategoryProductEdit">
         <sequence>
            <module name="Magento_Catalog"/>
         </sequence>
    </module>
</config>
We will provide Category Product edit link at admin by calling Admin event/observer. (adminhtml_block_html_before)

Create file at etc/adminhtml/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="adminhtml_block_html_before">
        <observer name="admin_category_product_edit_link_html_block_html_before_observer"
        	instance="Magelearn\CategoryProductEdit\Observer\AdminhtmlBlockHtmlBeforeObserver" />
    </event>
</config>

Call the observer file at Observer/AdminhtmlBlockHtmlBeforeObserver.php

<?php

declare(strict_types=1);

namespace Magelearn\CategoryProductEdit\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Event\Observer;
use Magento\Catalog\Block\Adminhtml\Category\Tab\Product;

class AdminhtmlBlockHtmlBeforeObserver implements ObserverInterface
{
    /**
     * Request instance
     *
     * @var RequestInterface
     */
    protected $request;

    /**
     * @param RequestInterface $request
     */
    public function __construct(
        RequestInterface $request
    ) {
        $this->request = $request;
    }

    /**
     * Add edit product column
     *
     * @param Observer $observer
     * @return void
     * @throws \Exception
     */
    public function execute(Observer $observer)
    {
        $block = $observer->getEvent()->getBlock();
        if (false === ($block instanceof Product)) {
            return;
        }
        
        $block->addColumn(
            'action',
            [
                'header' => __('Action'),
                'type' => 'action',
                'getter' => 'getId',
                'actions' => [
                    [
                        'caption' => __('Edit'),
                        'url' => [
                            'base' => 'catalog/product/edit',
                            'params' => ['store' => $this->request->getParam('store')]

                        ],
                        'field' => 'id'
                    ]
                ],
                'filter' => false,
                'sortable' => false,
                'index' => 'stores',
                'header_css_class' => 'col-action',
                'column_css_class' => 'col-action'
            ]
        );
    }
}
Now to provide the Category Products Thumbnail Image,
We will add etc/adminhtml/di.xml file and Override Category Product Tab class and add code to display category products image.
<?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\Block\Adminhtml\Category\Tab\Product" type="Magelearn\CategoryProductEdit\Block\Adminhtml\Category\Tab\Product" />
</config>
Now As per highlighted code above add 
Block/Adminhtml/Category/Tab/Product.php
<?php
declare(strict_types=1);

namespace Magelearn\CategoryProductEdit\Block\Adminhtml\Category\Tab;

use Magento\Framework\Data\Collection;
use Magelearn\CategoryProductEdit\Block\Adminhtml\Category\Tab\Product\Grid\Renderer\Image;
use Magento\Framework\Exception\LocalizedException;

class Product extends \Magento\Catalog\Block\Adminhtml\Category\Tab\Product
{
    /**
     * @var array
     */
    private array $thumbnailAttributes = ['thumbnail', 'small_image', 'image'];
    
    /**
     * Set collection object adding product thumbnail
     *
     * @param Collection $collection
     * @return void
     */
    public function setCollection($collection): void
    {
        // Add multiple image attributes for better fallback
        foreach ($this->thumbnailAttributes as $attribute) {
            $collection->addAttributeToSelect($attribute);
        }
        $this->_collection = $collection;
    }
    
    /**
     * Add column image with a custom renderer and after column entity_id
     *
     * @return Product
     * @throws LocalizedException
     */
    protected function _prepareColumns(): Product
    {
        parent::_prepareColumns();
        
        $this->addColumnAfter(
            'product_thumbnail',  // Changed from 'image' to be more specific
            [
                'header' => __('Thumbnail'),
                'index' => 'thumbnail',
                'renderer' => Image::class,
                'filter' => false,
                'sortable' => false,
                'column_css_class' => 'data-grid-thumbnail-cell',
                'header_css_class' => 'col-thumbnail'
            ],
            'entity_id'
            );
        
        $this->sortColumnsByOrder();
        
        return $this;
    }
}
Now as per the highlighted code above add our Image Renderer class at
Block/Adminhtml/Category/Tab/Product/Grid/Renderer/Image.php
<?php
declare(strict_types=1);

namespace Magelearn\CategoryProductEdit\Block\Adminhtml\Category\Tab\Product\Grid\Renderer;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Catalog\Helper\Image as ImageHelper;
use Magento\Framework\DataObject;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\Escaper;

class Image extends AbstractRenderer
{
    /**
     * @var ImageHelper
     */
    private ImageHelper $imageHelper;

    /**
     * @var StoreManagerInterface
     */
    private StoreManagerInterface $storeManager;

    /**
     * @var Escaper
     */
    private Escaper $escaper;

    /**
     * @param \Magento\Backend\Block\Context $context
     * @param ImageHelper $imageHelper
     * @param StoreManagerInterface $storeManager
     * @param Escaper $escaper
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Context $context,
        ImageHelper $imageHelper,
        StoreManagerInterface $storeManager,
        Escaper $escaper,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->imageHelper = $imageHelper;
        $this->storeManager = $storeManager;
        $this->escaper = $escaper;
    }

    /**
     * Render product thumbnail with fallback logic
     *
     * @param DataObject $row
     * @return string
     */
    public function render(DataObject $row): string
    {
        $imageUrl = $this->getProductImageUrl($row);
        $altText = $this->escaper->escapeHtmlAttr($row->getName());
        
        return sprintf(
            '<img src="%s" alt="%s" width="50" height="50" loading="lazy" class="admin__control-thumbnail"/>',
            $this->escaper->escapeUrl($imageUrl),
            $altText
        );
    }

    /**
     * Get product image URL with fallback logic
     *
     * @param DataObject $row
     * @return string
     */
    private function getProductImageUrl(DataObject $row): string
    {
        // Try thumbnail first
        if ($row->getThumbnail() && $row->getThumbnail() !== 'no_selection') {
            return $this->imageHelper->init($row, 'product_listing_thumbnail')
                ->setImageFile($row->getThumbnail())
                ->getUrl();
        }

        // Try small_image as fallback
        if ($row->getSmallImage() && $row->getSmallImage() !== 'no_selection') {
            return $this->imageHelper->init($row, 'product_listing_thumbnail')
                ->setImageFile($row->getSmallImage())
                ->getUrl();
        }

        // Try base image as last resort
        if ($row->getImage() && $row->getImage() !== 'no_selection') {
            return $this->imageHelper->init($row, 'product_listing_thumbnail')
                ->setImageFile($row->getImage())
                ->getUrl();
        }

        // Return placeholder if no images found
        return $this->imageHelper->getDefaultPlaceholderUrl('small_image');
    }
}
0 Comments On "Provide Category Product Edit Link and Category Product Thumbnail Image at Admin for Magento 2"

Back To Top