Magento2: How to add new grid in Category Listing Page
Here is a tutorial on how to add new Grid in Category Listing Page. For this example we will assume we want to add a grid same as Product Category Positions for Category Brands. It should look something like below:
Assume that you have a custom module called Namespace_Module. You will create following files in your module:
Namespace_Module\view\adminhtml\ui_component\category_form.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="my_custom_grid_positions" sortOrder="40">
<settings>
<collapsible>true</collapsible>
<label translate="true">My Custom Grid</label>
</settings>
<container name="assign_positions_container" sortOrder="160">
<htmlContent name="html_content">
<block name="my_custom_grid"
class="Namespace\Module\Block\Adminhtml\Category\MyCustomGrid"/>
</htmlContent>
</container>
</fieldset>
</form>
Namespace_Module\Block\Adminhtml\Category\MyCustomGrid.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
namespace Namespace\Module\Block\Adminhtml\Category;
/**
* Class MyCustomGrid
* @package Namespace\Module\Block\Adminhtml\Category
*/
class MyCustomGrid extends \Magento\Backend\Block\Template
{
/**
* Block template
*
* @var string
*/
protected $_template = 'Namespace_Module::catalog/category/edit/grid.phtml';
/**
* @var \Namespace\Module\Block\Adminhtml\Category\Tab\MyCustomGrid
*/
protected $blockGrid;
/**
* @var \Magento\Framework\Registry
*/
protected $registry;
/**
* @var \Magento\Framework\Json\EncoderInterface
*/
protected $jsonEncoder;
/**
* @var \Namespace\Module\Helper\Data
*/
protected $dataHelper;
/**
* MyCustomGrid constructor.
*
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
* @param \Namespace\Module\Helper\Data $dataHelper
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Json\EncoderInterface $jsonEncoder,
\Namespace\Module\Helper\Data $dataHelper,
array $data = []
) {
$this->dataHelper = $dataHelper;
$this->registry = $registry;
$this->jsonEncoder = $jsonEncoder;
parent::__construct($context, $data);
}
/**
* Retrieve instance of grid block
*
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function getBlockGrid()
{
if (null === $this->blockGrid) {
$this->blockGrid = $this->getLayout()->createBlock(
\Namespace\Module\Block\Adminhtml\Category\Tab\MyCustomGrid::class,
'category.mycustom.grid'
);
}
return $this->blockGrid;
}
/**
* Return HTML of grid block
*
* @return string
*/
public function getGridHtml()
{
return $this->getBlockGrid()->toHtml();
}
/**
* @return string
*/
public function getGridJson()
{
$category = $this->getCategory();
$categoryId = $category->getId();
$positionArr = $this->dataHelper->getPositions($categoryId);
if (!empty($positionArr)) {
return $this->jsonEncoder->encode($positionArr);
}
return '{}';
}
/**
* Retrieve current category instance
*
* @return array|null
*/
public function getCategory()
{
return $this->registry->registry('category');
}
}
Namespace_Module\view\adminhtml\templates\catalog\category\edit\assign.phtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
/** @var \Namespace\Module\Block\Adminhtml\Category\MyCustomGrid $block */
/** @var \Namespace\Module\Block\Adminhtml\Category\Tab\MyCustomGrid $blockGrid */
//PLEASE USE PROPER NAMING CONVENTION. EVERYTHING BELOW IS JUST FOR EXAMPLE PURPOSES.
$blockGrid = $block->getBlockGrid();
$gridJsObjectName = $blockGrid->getJsObjectName();
?>
<?= $block->getGridHtml() ?>
<input type="hidden" name="my_custom_grid_data" id="in_grid_data" data-form-part="category_form" value="" />
<script type="text/x-magento-init">
{
"*": {
"Namespace_Module/catalog/category/assign": {
"selectedRows": <?= /* @noEscape */ $block->getGridJson() ?>,
"gridJsObjectName": <?= /* @noEscape */ '"' . $gridJsObjectName . '"' ?: '{}' ?>
}
}
}
</script>
<!-- @todo remove when "UI components" will support such initialization -->
<script>
require('mage/apply/main').apply();
</script>
Namespace_Module\view\adminhtml\web\catalog\category\edit\assign.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
/* global $, $H */
define([
'mage/adminhtml/grid'
], function () {
'use strict';
return function (config) {
var selectedRows = config.selectedRows,
categoryRows = $H(selectedRows),
gridJsObject = window[config.gridJsObjectName];
$('in_grid_data').value = Object.toJSON(categoryRows);
/**
* Change product position
*
* @param {String} event
*/
function positionChange(event) {
var element = Event.element(event);
if (element && element.entityElement) {
categoryRows.set(element.entityElement.innerText, element.value);
$('in_grid_data').value = Object.toJSON(categoryRows);
}
}
/**
* Initialize category product row
*
* @param {Object} grid
* @param {String} row
*/
function categoryProductRowInit(grid, row) {
var entityId = $(row).getElementsByClassName('col-entity_id')[0],
position = $(row).getElementsByClassName('input-text')[0];
if (entityId && position) {
entityId.positionElement = position;
position.entityElement = entityId;
Event.observe(position, 'keyup', positionChange);
}
}
gridJsObject.initRowCallback = categoryProductRowInit;
if (gridJsObject.rows) {
gridJsObject.rows.each(function (row) {
categoryProductRowInit(gridJsObject, row);
});
}
};
});
Namespace_Module\Controller\Adminhtml\Category\Assign.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
namespace Namespace\Module\Controller\Adminhtml\Category;
class Assign extends \Magento\Catalog\Controller\Adminhtml\Category
{
/**
* @var \Magento\Framework\Controller\Result\RawFactory
*/
protected $resultRawFactory;
/**
* @var \Magento\Framework\View\LayoutFactory
*/
protected $layoutFactory;
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory
* @param \Magento\Framework\View\LayoutFactory $layoutFactory
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
\Magento\Framework\View\LayoutFactory $layoutFactory
) {
parent::__construct($context);
$this->resultRawFactory = $resultRawFactory;
$this->layoutFactory = $layoutFactory;
}
/**
* Grid Action
* Display list of products related to current category
*
* @return \Magento\Framework\Controller\Result\Raw
*/
public function execute()
{
$category = $this->_initCategory(true);
if (!$category) {
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
return $resultRedirect->setPath('catalog/*/', ['_current' => true, 'id' => null]);
}
/** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
$resultRaw = $this->resultRawFactory->create();
return $resultRaw->setContents(
$this->layoutFactory->create()->createBlock(
\Namespace\Module\Block\Adminhtml\Category\Tab\MyCustomGrid::class,
'category.mycustom.grid'
)->toHtml()
);
}
}
Namespace_Module\Block\Adminhtml\Category\Tab\MyCustomGrid.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
namespace Namespace\Module\Block\Adminhtml\Category\Tab;
/**
* Class MyCustomGrid
*/
class MyCustomGrid extends \Magento\Backend\Block\Widget\Grid\Extended
{
/**
* Core registry
*
* @var \Magento\Framework\Registry
*/
protected $_coreRegistry = null;
/**
* @var \Namespace\Module\Model\MyModelFactory
*/
protected $myModelFactory;
/**
* MyCustomGrid constructor.
*
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Backend\Helper\Data $backendHelper
* @param \Namespace\Module\Model\MyModelFactory $myModelFactory
* @param \Magento\Framework\Registry $coreRegistry
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Backend\Helper\Data $backendHelper,
\Namespace\Module\Model\MyModelFactory $myModelFactory,
\Magento\Framework\Registry $coreRegistry,
array $data = []
) {
parent::__construct($context, $backendHelper, $data);
$this->myModelFactory = $myModelFactory;
$this->_coreRegistry = $coreRegistry;
}
/**
* @return void
*/
protected function _construct()
{
parent::_construct();
$this->setId('my_custom_grid');
$this->setDefaultSort('position');
$this->setUseAjax(true);
}
/**
* @return array|null
*/
public function getCategory()
{
return $this->_coreRegistry->registry('category');
}
/**
* @return MyCustomGrid
*/
protected function _prepareCollection()
{
if ($this->getCategory()->getId()) {
$this->setDefaultFilter(['in_category' => 1]);
}
$collection = $this->myModelFactory->create()->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
/**
* @return MyCustomGrid
* @throws \Exception
*/
protected function _prepareColumns()
{
$this->addColumn(
'entity_id',
[
'header' => __('ID'),
'sortable' => true,
'index' => 'entity_id',
'header_css_class' => 'col-id',
'column_css_class' => 'col-id'
]
);
$this->addColumn('value', ['header' => __('My Name Column'), 'index' => 'value']);
$this->addColumn(
'position',
[
'header' => __('Position'),
'type' => 'number',
'index' => 'position',
'editable' => true
]
);
return parent::_prepareColumns();
}
/**
* @return string
*/
public function getGridUrl()
{
return $this->getUrl('moduleFrontName/*/assign', ['_current' => true]);
}
}
For saving, updating and deleting the positions you need to create plugin on category save which takes the posted json, compares with original json and performs the required operation.
Comments
Post a Comment