0

How to add a custom grid in a new tab in product edit page using UI_Component method?

This custom grid fetches collection from a custom table.

1

You can add it using modifier and UI component. Let's say my module name is Codextblog/Customtab.

Add Modifier app/code/Codextblog/Customtab/etc/adminhtml/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
    <arguments>
        <argument name="modifiers" xsi:type="array">
            <item name="custom-tab-with-content" xsi:type="array">
                <item name="class" xsi:type="string">Codextblog\Customtab\Ui\DataProvider\Product\Form\Modifier\CustomTab</item>
                <item name="sortOrder" xsi:type="number">10</item>
            </item>
        </argument>
    </arguments>
</virtualType>
</config>

Add custom tab

<?php
namespace Codextblog\Customtab\Ui\DataProvider\Product\Form\Modifier;

use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Framework\UrlInterface;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\Form\Fieldset;


class CustomTab extends AbstractModifier
{

const SAMPLE_FIELDSET_NAME = 'custom_fieldset';
const SAMPLE_FIELD_NAME = 'is_custom';


protected $_backendUrl;
protected $_productloader;
protected $_modelCustomtabFactory;

/**
 * @var \Magento\Catalog\Model\Locator\LocatorInterface
 */
protected $locator;

/**
 * @var ArrayManager
 */
protected $arrayManager;

/**
 * @var UrlInterface
 */
protected $urlBuilder;

/**
 * @var array
 */
protected $meta = [];

/**
 * @param LocatorInterface $locator
 * @param ArrayManager $arrayManager
 * @param UrlInterface $urlBuilder
 */
public function __construct(
    LocatorInterface $locator,
    ArrayManager $arrayManager,
    UrlInterface $urlBuilder,
    \Magento\Catalog\Model\ProductFactory $_productloader,
    \Magento\Backend\Model\UrlInterface $backendUrl
) {
    $this->locator = $locator;
    $this->arrayManager = $arrayManager;
    $this->urlBuilder = $urlBuilder;
    $this->_productloader = $_productloader;
    $this->_backendUrl = $backendUrl;
}

public function modifyData(array $data)
{
    return $data;
}

public function modifyMeta(array $meta)
{
    $this->meta = $meta;
    $this->addCustomTab();

    return $this->meta;
}

protected function addCustomTab()
{
    $this->meta = array_merge_recursive(
        $this->meta,
        [
            static::SAMPLE_FIELDSET_NAME => $this->getTabConfig(),
        ]
    );
}

protected function getTabConfig()
{
    return [
        'arguments' => [
            'data' => [
                'config' => [
                    'label' => __('Custom Tab'),
                    'componentType' => Fieldset::NAME,
                    'dataScope' => '',
                    'provider' => static::FORM_NAME . '.product_form_data_source',
                    'ns' => static::FORM_NAME,
                    'collapsible' => true,
                ],
            ],
        ],
        'children' => [
            static::SAMPLE_FIELD_NAME => [
                'arguments' => [
                    'data' => [
                        'config' => [
                            'autoRender' => true,
                            'componentType' => 'insertListing',
                            'dataScope' => 'custom_listing',
                            'externalProvider' => 'custom_listing.custom_listing_data_source',
                            'selectionsProvider' => 'custom_listing.custom_listing.product_columns.ids',
                            'ns' => 'custom_listing',
                            'render_url' => $this->urlBuilder->getUrl('mui/index/render'),
                            'realTimeLink' => false,
                            'behaviourType' => 'simple',
                            'externalFilterMode' => true,
                            'imports' => [
                                'productId' => '${ $.provider }:data.product.current_product_id'
                            ],
                            'exports' => [
                                'productId' => '${ $.externalProvider }:params.current_product_id'
                            ],

                        ],
                    ],
                ],
                'children' => [],
            ],
        ],
    ];
}

}

Add dataprovider file app/code/Codextblog/Customtab/Ui/Dataprovider/Product/CustomDataProvider.php

<?php

namespace Codextblog\Customtab\Ui\DataProvider\Product;

use Magento\Framework\App\RequestInterface;
use Magento\Ui\DataProvider\AbstractDataProvider;
use Codextblog\Custom\Model\ResourceModel\Custom\CollectionFactory;
use Codextblog\Custom\Model\ResourceModel\Custom\Collection;
use Codextblog\Custom\Model\Custom;


class CustomDataProvider extends AbstractDataProvider
{
/**
 * @var CollectionFactory
 */
protected $collectionFactory;

/**
 * @var RequestInterface
 */
protected $request;

/**
 * @param string $name
 * @param string $primaryFieldName
 * @param string $requestFieldName
 * @param CollectionFactory $collectionFactory
 * @param RequestInterface $request
 * @param array $meta
 * @param array $data
 */
public function __construct(
    $name,
    $primaryFieldName,
    $requestFieldName,
    CollectionFactory $collectionFactory,
    RequestInterface $request,
    array $meta = [],
    array $data = []
) {
    parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    $this->collectionFactory = $collectionFactory;
    $this->collection = $this->collectionFactory->create();
    $this->request = $request;
}

/**
 * {@inheritdoc}
 */
public function getData()
{
    $this->getCollection();

    $arrItems = [
        'totalRecords' => $this->getCollection()->getSize(),
        'items' => [],
    ];

    foreach ($this->getCollection() as $item) {
        $arrItems['items'][] = $item->toArray([]);
    }

    return $arrItems;
}

/**
 * {@inheritdoc}
 */
public function addFilter(\Magento\Framework\Api\Filter $filter)
{
    $field = $filter->getField();



    if (in_array($field, ['title', 'nickname', 'detail'])) {
        $filter->setField($field);
    }

    parent::addFilter($filter);
}
}

Here Codextblog\Custom\Model\ResourceModel\Custom\CollectionFactory is the collection of a module which grid will be display in a custom tab.

Create ui component app/code/Codextblog/Customtab/view/adminhtml/ui_component/custom_listing.xml

<?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">
<argument name="data" xsi:type="array">
    <item name="js_config" xsi:type="array">
        <item name="provider" xsi:type="string">custom_listing.custom_listing_data_source</item>
        <item name="deps" xsi:type="string">custom_listing.custom_listing_data_source</item>
    </item>
    <item name="spinner" xsi:type="string">custom_columns</item>
</argument>
<dataSource name="custom_listing_data_source">
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">Codextblog\Customtab\Ui\DataProvider\Product\CustomDataProvider</argument>
        <argument name="name" xsi:type="string">custom_listing_data_source</argument>
        <argument name="primaryFieldName" xsi:type="string">id</argument>
        <argument name="requestFieldName" xsi:type="string">id</argument>
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                <item name="update_url" xsi:type="url" path="mui/index/render"/>
                <item name="storageConfig" xsi:type="array">
                    <item name="cacheRequests" xsi:type="boolean">false</item>
                </item>
            </item>
        </argument>
    </argument>
</dataSource>
<listingToolbar name="listing_top">
    <filters name="listing_filters">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="statefull" xsi:type="array">
                    <item name="applied" xsi:type="boolean">false</item>
                </item>
                <item name="params" xsi:type="array">
                    <item name="filters_modifier" xsi:type="array"/>
                </item>
            </item>
        </argument>
    </filters>
    <paging name="listing_paging"/>
</listingToolbar>
<columns name="custom_columns" class="Magento\Ui\Component\Listing\Columns">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="childDefaults" xsi:type="array">
                <item name="fieldAction" xsi:type="array">
                    <item name="provider" xsi:type="string">customGrid</item>
                    <item name="target" xsi:type="string">selectReview</item>
                    <item name="params" xsi:type="array">
                        <item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
                    </item>
                </item>
            </item>
        </item>
    </argument>
    <column name="id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">textRange</item>
                <item name="sorting" xsi:type="string">asc</item>
                <item name="label" xsi:type="string" translate="true">ID</item>
                <item name="sortOrder" xsi:type="number">0</item>
            </item>
        </argument>
    </column>
    <column name="name">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Name</item>
                <item name="sortOrder" xsi:type="number">30</item>
                <item name="truncate" xsi:type="number">50</item>
                <item name="nl2br" xsi:type="boolean">true</item>
                <item name="escape" xsi:type="boolean">true</item>
            </item>
        </argument>
    </column>
</columns>
</listing>
  • I need the the custom table collection based on the product_id, in that collection how can i add current product id for the collection filter(CustomDataProvider.php) – senthil Apr 8 at 14:03
  • @senthil Did you try this $this->getRequest()->getParam('id'); – chirag dodia Apr 9 at 4:46
  • Yes, but i am getting the following error. Fatal error: Method Magento\Ui\TemplateEngine\Xhtml\Result::__toString() must not throw an exception, caught Error: Call to undefined method Learn\ProductQA\Ui\DataProvider\Product\QuestionAnswerDataProvider::getRequest() in D:\workspace\Magento\m226\vendor\magento\module-ui\Controller\Adminhtml\Index\Render.php on line 0 So, instead of that i used the $this->_request->getParams(), but in this i don't see any product_id, because the grid load by ajax – senthil Apr 9 at 5:19
  • @mariun , how can i get the current product id in the product edit page custom tab collection grid, i tried $_REQUEST , it returning Array ( [namespace] => questionanswer_grid_listing [isAjax] => true ) – senthil Apr 26 at 6:41

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.