2

How to add more column to "category product" grid of categories admin in Magento 2.0. enter image description here

If can, please show me step by step!

  • Did you find a solution for this? – BvdVen Nov 14 '16 at 10:50
  • Oki, I'll answer my solution a minute. – MrTo-Kane Nov 16 '16 at 4:39
1

My solution below: Create new module "CustomPro" and some files noted below:
1) etc/di.xml :

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Block\Adminhtml\Category\Tab\Product" type="Tohq\CustomPro\Block\Adminhtml\Category\Tab\CustomProduct" />
</config>

2) Create file: Tohq\CustomPro\Block\Adminhtml\Category\Tab\CustomProduct.php

<?php
namespace Tohq\CustomPro\Block\Adminhtml\Category\Tab;

use \Magento\Backend\Block\Widget\Grid\Extended;
use \Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Block\Adminhtml\Category\Tab\Product;

class CustomProduct extends \Magento\Catalog\Block\Adminhtml\Category\Tab\Product
{

    public function __construct(\Magento\Backend\Block\Template\Context $context, \Magento\Backend\Helper\Data $backendHelper, \Magento\Catalog\Model\ProductFactory $productFactory, \Magento\Framework\Registry $coreRegistry, array $data = [])
    {
        parent::__construct($context, $backendHelper, $productFactory, $coreRegistry);
    }

    /**
     *
     * @return Grid
     */
    protected function _prepareCollection()
    {
        if ($this->getCategory()->getId()) {
            $this->setDefaultFilter([
                'in_category' => 1
            ]);
        }

        $collection = $this->_productFactory->create()
            ->getCollection()
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('image')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('status')
            ->addAttributeToSelect('price')
            ->addAttributeToSelect('period_date_start')
            ->addAttributeToSelect('period_date_end')
            ->addStoreFilter($this->getRequest()
            ->getParam('store'))
            ->joinField('position', 'catalog_category_product', 'position', 'product_id=entity_id', 'category_id=' . (int) $this->getRequest()
            ->getParam('id', 0), 'left');
        $this->setCollection($collection);

        if ($this->getCategory()->getProductsReadonly()) {
            $productIds = $this->_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            $this->getCollection()->addFieldToFilter('entity_id', [
                'in' => $productIds
            ]);
        }

        // begin modify
        Extended::_prepareCollection();

        $collection = $this->getCollection();

        return $this;
    }

    /**
     *
     * @return Extended
     */
    protected function _prepareColumns()
    {
        $this->addColumnAfter('status', [
            'header' => __('Status'),
            'index' => 'status',
            'options' => ProductHelperData::getOptionStatus(),
            'type' => 'options',
            'sortable' => true,
            'header_css_class' => 'col-action',
            'column_css_class' => 'col-action',
            'renderer' => 'Tohq\CustomPro\Block\Adminhtml\Product\Helper\Form\Options'
        ], 'entity_id');
        return parent::_prepareColumns();
    }
}

3) Create file: Tohq\CustomPro\Block\Adminhtml\Product\Helper\Form\Options.php

<?php

namespace Tohq\CustomPro\Block\Adminhtml\Product\Helper\Form;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Tohq\CustomPro\Helper\Data as HelperData;
class Options extends AbstractRenderer
{
    public function render(DataObject $row)
    {


        $attributesArrays = HelperData::getOptionStatus();
        if (!empty($row) && !empty($this->_getValue($row))) {

            $value=$this->_getValue($row);

            if(!empty(HelperData::COLORS[$value])){
                $color=HelperData::COLORS[$value];

                return  sprintf($color,$attributesArrays[$value]);
            }

            return null;
        } else {
            return null;
        }
    }
}

4) Create file:Tohq\CustomPro\Helper\Data

<?php

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Tohq\CustomPro\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Cms\Helper\Page;
use Monolog\Logger as MonologLogger;
use Monolog\Handler\RotatingFileHandler; 

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{

    /**
     *
     * @var STATUS_ONLINE
     */
    const STATUS_ONLINE = 1;

    /**
     *
     * @var STATUS_OFFLINE
     */
    const STATUS_OFFLINE = 2;

    /**
     *
     * @var STATUS_IN_COMMING
     */
    const STATUS_IN_COMMING = 3;

    /**
     *
     * @var STATUS_OVER_DATE
     */
    const STATUS_OVER_DATE = 4;

    /**
     *
     * @var \Magento\Catalog\Model\Product
     */
    private $productModel;

    /**
     *
     * @return array|null
     */

    private $logger=null;
    const COLORS = [
        self::STATUS_ONLINE => "<span class='status status-online'>%s</span>",
        self::STATUS_OFFLINE => "<span class='status status-offline'>%s</span>",
        self::STATUS_IN_COMMING => "<span class='status status-in-comming'>%s</span>",
        self::STATUS_OVER_DATE => "<span class='status status-over'>%s</span>"
    ];

    /**
     *
     * @param Context $context            
     */
    public function __construct(\Magento\Catalog\Model\Product $product, \Magento\Framework\App\Helper\Context $context)
    {
        $this->productModel = $product;
        parent::__construct($context);


    }

    /**
     *
     * @return array
     */
    public static function getOptionStatus()
    {
        return [
            self::STATUS_ONLINE => __("Display Product"),
            self::STATUS_OFFLINE => __("Undisplay Product"),
            self::STATUS_IN_COMMING => __("Before Display Product"),
            self::STATUS_OVER_DATE => __("Overdate display Product")
        ];
    }
    /**
     * 
     * @param \Magento\Catalog\Model\Product $productData
     */
    public function changeProductStatus(\Magento\Catalog\Model\Product &$productData)
    {
        $status = $productData->getStatus();
        $typeId = $productData->getTypeId();

        $startDate = $productData->getData("period_date_start");
        $startDate = ! empty($startDate) ? strtotime($startDate) : 0;

        $endDate   = $productData->getData("period_date_end");
        $endDate   = ! empty($endDate)   ? strtotime($endDate)   : 0;

        $om = \Magento\Framework\App\ObjectManager::getInstance();
        $datetime = $om->get('Magento\Framework\Stdlib\DateTime\DateTime');

        $current = time() + $datetime->getGmtOffset();

        if ( $status == self::STATUS_ONLINE && $startDate == 0 && $endDate == 0 ) $productData->setStatus(self::STATUS_ONLINE);
        elseif ( $status == self::STATUS_ONLINE && $current > $startDate && $endDate == 0) $productData->setStatus(self::STATUS_ONLINE);
        elseif ( $status == self::STATUS_ONLINE && $current > $startDate && $current < $endDate ) $productData->setStatus(self::STATUS_ONLINE);
        elseif ( $status == self::STATUS_ONLINE && $current < $startDate ) $productData->setStatus(self::STATUS_IN_COMMING);
        elseif ( $status == self::STATUS_ONLINE && $current > $endDate ) $productData->setStatus(self::STATUS_OVER_DATE);
        else $productData->setStatus(self::STATUS_OFFLINE);

        return $productData;
    }

    /**
     *
     * @param unknown $collection            
     * @param string $status            
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    public function applyStatusFilterToCollection(\Magento\Catalog\Model\ResourceModel\Product\Collection &$collection, $status = null)
    {
        if (empty($collection))
            return;

        $removed = 0;
        if ($status) {

            $today = date('Y-m-d H:i:s');
            if (in_array($status, [
                self::STATUS_IN_COMMING,
                self::STATUS_OVER_DATE,
                self::STATUS_ONLINE
            ])) {
                $collection->addFieldToFilter('status', [
                    'eq' => self::STATUS_ONLINE
                ]);

                if ($status == self::STATUS_IN_COMMING) {

                    $collection->addFieldToFilter('type_id', [
                        'eq' => 'grouped'
                    ]);
                    $collection->addFieldToFilter('period_date_start', [
                        'gt' => $today
                    ]);
                } elseif ($status == self::STATUS_OVER_DATE) {

                    $collection->addFieldToFilter('type_id', [
                        'eq' => 'grouped'
                    ]);
                    $collection->addFieldToFilter('period_date_end', [
                        'lt' => $today
                    ]);
                } elseif ($status == self::STATUS_ONLINE) {
                    $nowTimeStamp = strtotime($today);
                    foreach ($collection as $el) {

                        if ($el->getTypeID() == "grouped") {

                            $_product = $this->productModel->load($el->getId());
                            if (empty($_product))
                                continue;
                            $dateStart = $_product->getData('period_date_start');
                            $dateEnd = $_product->getData('period_date_end');

                            if (empty($dateStart) && empty($dateEnd))
                                continue;

                            if (! (strtotime($dateStart) <= $nowTimeStamp && $nowTimeStamp <= strtotime($dateEnd))) {

                                $removed ++;
                                $collection->removeItemByKey($el->getId());
                            }
                        }
                    }
                }
            } elseif ($status == self::STATUS_OFFLINE) {
                $collection->addFieldToFilter('status', [
                    'eq' => self::STATUS_OFFLINE
                ]);
            }
        }

        if ($collection) {
            foreach ($collection as &$el) {

                $this->changeProductStatus($el);
            }
        }

        if (method_exists($collection, "reSetTotalRecords"))
            $collection->reSetTotalRecords($removed);

        return $collection;
    }
}
  • I've created a module and added the files and ran "setup:upgrade". I see the module in "Stores->Configuration->Advanced->Advanced". But in the "category product" grid I don't see any new column or something that it is working. Do I miss something? – BvdVen Nov 16 '16 at 15:40
  • I have tried this but not working . can you share working code ? – Mukesh Prajapati Nov 3 '18 at 7:54
  • This code is not working in Magento Enterprise Edition, Can anyone plz tell me how we can override Magento\VisualMerchandiser\Block\Adminhtml\Category\Merchandiser\Grid.php – Ashna Apr 27 at 12:31

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.