12

I want to add new tab in product edit page and for that i have follow this steps :

  1. Create di.xml and add below code:

    <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
        <arguments>
            <argument name="modifiers" xsi:type="array">
                <item name="custommodule" xsi:type="array">
                    <item name="class" xsi:type="string">Namespace\Custommodule\Ui\DataProvider\Product\Modifier\Customtab</item>
                    <item name="sortOrder" xsi:type="number">200</item>
                </item>
            </argument>
        </arguments>
    </virtualType>
    
  2. Create Customtab.php and by modifyMeta() function new tab is created.

Now I want to call custom phtml file to render html. How can I call custom phtml file ?

2
  • Hello, I am doing something kind of same. Did you get the way? Kindly update the ans if you have. Thanks in Advance!!
    – Rushvi
    Commented Jul 28, 2016 at 5:19
  • Thanks Jaimin, today it helps me a lot to resolve issue :) +5 from me
    – Keyur Shah
    Commented Jan 19, 2017 at 12:39

1 Answer 1

16
+50

I have take reference for configurable product and followed below steps. Here may be some code is not usable.

1) Create app/code/Namespace/Modulename/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="modulename" xsi:type="array">
                    <item name="class" xsi:type="string">Namespace\Modulename\Ui\DataProvider\Product\Modifier\Customtab</item>
                    <item name="sortOrder" xsi:type="number">200</item>
                </item>
            </argument>
        </arguments>
    </virtualType>

     <type name="Namespace\Modulename\Ui\DataProvider\Product\Modifier\Customtab">
        <arguments>
            <argument name="formName" xsi:type="string">product_form</argument>
            <argument name="dataScopeName" xsi:type="string">product_form.product_form</argument>
            <argument name="dataSourceName" xsi:type="string">product_form.product_form_data_source</argument>
        </arguments>
    </type>
</config>

2) Create app/code/Namespace/Modulename/Ui/DataProvider/Product/Modifier/Customtab.php

<?php

namespace Namespace\Modulename\Ui\DataProvider\Product\Modifier;

use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Store\Api\WebsiteRepositoryInterface;
use Magento\Store\Api\GroupRepositoryInterface;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Ui\Component\Form;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;

class Customtab extends AbstractModifier
{
    const SORT_ORDER = 40;

    protected $locator;

    protected $websiteRepository;

    protected $groupRepository;

    protected $storeRepository;

    protected $websitesOptionsList;

    protected $storeManager;

    protected $websitesList;

    private $dataScopeName;

    public function __construct(
        LocatorInterface $locator,
        StoreManagerInterface $storeManager,
        WebsiteRepositoryInterface $websiteRepository,
        GroupRepositoryInterface $groupRepository,
        StoreRepositoryInterface $storeRepository,
        $dataScopeName
    ) {
        $this->locator = $locator;
        $this->storeManager = $storeManager;
        $this->websiteRepository = $websiteRepository;
        $this->groupRepository = $groupRepository;
        $this->storeRepository = $storeRepository;
        $this->dataScopeName = $dataScopeName;
    }

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

    public function modifyMeta(array $meta)
    {
        if (!$this->storeManager->isSingleStoreMode()) {
            $meta = array_replace_recursive(
                $meta,
                [
                    'tabname' => [
                        'arguments' => [
                            'data' => [
                                'config' => [
                                    'additionalClasses' => 'admin__fieldset-product-customclass',
                                    'label' => __('Your Label'),
                                    'collapsible' => true,
                                    'componentType' => Form\Fieldset::NAME,
                                    'sortOrder' => $this->getNextGroupSortOrder(
                                        $meta,
                                        'search-engine-optimization',
                                        self::SORT_ORDER
                                    ),
                                ],
                            ],
                        ],
                        'children' => $this->getPanelChildren(),
                    ],
                ]
            );
        }

        return $meta;
    }

    protected function getPanelChildren()
    {
        return [
            'tabname_products_button_set' => $this->getButtonSet()

        ];
    }

    protected function getButtonSet()
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'component' => 'Namespace_Modulename/js/components/container-tabname-handler',
                        'formElement' => 'container',
                        'componentType' => 'container',
                        'label' => false,
                        'content1' => __(
                            'Add some content'
                        ),
                        'template' => 'ui/form/components/complex',
                        'createTabButton' => 'ns = ${ $.ns }, index = create_tabname_products_button',
                    ],
                ],
            ],
            'children' => [

                'create_tabname_products_button' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'formElement' => 'container',
                                'componentType' => 'container',
                                'component' => 'Magento_Ui/js/form/components/button',
                                'actions' => [
                                    [
                                        'targetName' => $this->dataScopeName.'.customModal',
                                        'actionName' => 'trigger',
                                        'params' => ['active', true],
                                    ],
                                    [
                                        'targetName' => $this->dataScopeName.'.customModal',
                                        'actionName' => 'openModal',
                                    ],
                                ],
                                'title' => __('Your Title'),
                                'sortOrder' => 20,

                            ],
                        ],
                    ],
                ],
            ],
        ];
    }
}

3) Create app/code/Namespace/Modulename/view/adminhtml/layout/catalog_product_new.xml

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">

    <body>
         <referenceBlock name="product_form">
            <block name="product.form.modulename.matrix" class="Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Matrix" template="Namespace_Modulename::catalog/product/edit/tab/custom.phtml" as="product_custom">
                <arguments>
                    <argument name="config" xsi:type="array">
                        <item name="collapsible" xsi:type="boolean">false</item>
                        <item name="label" xsi:type="string" translate="true" />
                        <item name="sortOrder" xsi:type="string">1000</item>
                        <item name="canShow" xsi:type="boolean">true</item>
                        <item name="componentType" xsi:type="string">fieldset</item>
                        <item name="provider" xsi:type="string">product_form.product_form_data_source</item>
                        <item name="form" xsi:type="string">product_form.product_form</item>
                        <item name="modal" xsi:type="string">customModal</item>
                        <item name="nameStepWizard" xsi:type="string">variation-steps-wizard</item>
                        <item name="dataScope" xsi:type="string">productFormCustommodule</item>
                        <item name="urlWizard" xsi:type="string">modulename/index/custom</item>
                    </argument>
                </arguments>
            </block>
        </referenceBlock>
    </body>
</page>

4) Create layout file for action app/code/Namespace/Modulename/view/adminhtml/layout/modulename_index_custom.xml

<?xml version="1.0" ?>

<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
    <container name="root" label="Root">
        <block class="Namespace\Modulename\Block\Adminhtml\Catalog\Product\Edit\Tab\Custom" template="catalog/product/edit/tab/customfile.phtml" name="product_custom">

        </block> 
    </container>
</layout>

5) Create block file app/code/Namespace/Modulename/Block/Adminhtml/Catalog/Product/Edit/Tab/Custom.php

<?php


namespace Namespace\Modulename\Block\Adminhtml\Catalog\Product\Edit\Tab;


class Custom extends \Magento\Backend\Block\Widget implements \Magento\Backend\Block\Widget\Tab\TabInterface
{
    protected $_template = 'catalog/product/edit/tab/custom.phtml';


    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    protected function _prepareLayout()
    {

        return parent::_prepareLayout();
    }
}

6) Create controller file for action app/code/Namespace/Modulename/Controller/Adminhtml/Index/Custom.php

<?php

namespace Namespace\Modulename\Controller\Adminhtml\Index;

class Custom extends \Magento\Framework\App\Action\Action
{
    protected $_resultPageFactory;
    protected $resultJsonFactory;
    protected $_errorHelper;

    /**
     * @param \Magento\Framework\App\Action\Context           $context
     * @param \Magento\Framework\View\Result\PageFactory      $resultPageFactory
     * @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory
     */
    public function __construct(
    \Magento\Framework\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Framework\Controller\Result\RawFactory $resultRawFactory
    ) {
        $this->_resultPageFactory = $resultPageFactory;

        $this->resultRawFactory = $resultRawFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        $resultPage = $this->_resultPageFactory->create();
        $block = $resultPage->getLayout()->getBlock('product_custom');
        $this->getResponse()->appendBody($block->toHtml());
    }
}

7) Create template file app/code/Namespace/Modulename/view/adminhtml/templates/catalog/product/edit/tab/custom.phtml

<div class="<?= /* @noEscape */ $block->getData('config/dataScope') ?>" data-role="step-wizard-dialog" data-bind="scope: '<?= /* @noEscape */ $block->getForm() ?>.<?= /* @noEscape */ $block->getModal() ?>'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>
<div class="<?= /* @noEscape */ $block->getData('config/dataScope') ?>" id="product-variations-matrix" data-role="product-variations-matrix">
    <div data-bind="scope: 'configurableVariations'"></div>
</div>
<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "<?= /* @noEscape */ $block->getData('config/form') ?>.<?= /* @noEscape */ $block->getModal() ?>": {
                        "component": "Namespace_Modulename/js/components/modal-custommodule",
                        "options": {"type": "slide", "title": "<?php echo $block->escapeHtml(__('Your Title')); ?>"},
                        "formName": "<?= /* @noEscape */ $block->getForm() ?>",
                        "isTemplate": false,
                        "stepWizard": "<?= /* @noEscape */ $block->getData('config/nameStepWizard') ?>",
                        "children": {
                            "wizard": {
                                "url": "<?= /* @noEscape */ $block->getUrl($block->getData('config/urlWizard'), ['id' => $block->getProduct()->getId()]) ?>",
                                "component": "Magento_Ui/js/form/components/html"
                            }
                        }
                    }

                }
            }
        }
    }
</script>

<script>
    require(['jquery', 'mage/apply/main'], function ($, main) {
        main.apply();

          $('.<?= /* @noEscape */ $block->getData('config/dataScope') ?>[data-role=step-wizard-dialog]').applyBindings();
        $('.<?= /* @noEscape */ $block->getData('config/dataScope') ?>[data-role=product-variations-matrix]').applyBindings();

    })
</script>

8) Create my custom phtml file app/code/Namespace/Modulename/view/adminhtml/templates/catalog/product/edit/tab/customfile.phtml and write my code here.

9) Create Js app/code/Namesapce/Modulename/view/adminhtml/web/js/components/modal-custommodule.js

define([
    'Magento_Ui/js/modal/modal-component',
    'uiRegistry',
    'underscore'
], function (Modal, registry, _) {
    'use strict';

    return Modal.extend({
        defaults: {
            stepWizard: '',
            modules: {
                form: '${ $.formName }'
            }
        },

        /**
         * Open modal
         */
        openModal: function () {
            var stepWizard = {};

            this.form().validate();

            if (this.form().source.get('params.invalid') === false) {
                stepWizard = registry.get('index = ' + this.stepWizard);

                if (!_.isUndefined(stepWizard)) {
                    stepWizard.open();
                }

                this._super();
            }
        }
    });
});

10 ) Create Js app/code/Namesapce/Modulename/view/adminhtml/web/js/components/container-tabname-handler.js

define([
    'uiComponent'
], function (Element) {
    'use strict';

    return Element.extend({
        defaults: {
            listens: {
                '${ $.provider }:data.is_downloadable': 'handleProductType'
            },
            links: {
                isDownloadable: '${ $.provider }:data.is_downloadable'
            },
            modules: {
                createConfigurableButton: '${$.createConfigurableButton}'
            }
        },

        /**
         * Invokes initialize method of parent class,
         * contains initialization logic
         */
        initialize: function () {
            this._super();
            this.handleProductType(this.isDownloadable);

            return this;
        },

        /**
         * Calls 'initObservable' of parent
         *
         * @returns {Object} Chainable.
         */
        initObservable: function () {
            this._super()
                .observe(['content']);

            return this;
        },

        /**
         * Change content for container and visibility for button
         *
         * @param {String} isDownloadable
         */
        handleProductType: function (isDownloadable) {
            if (isDownloadable === '1') {
                this.content(this.content2);

                if (this.createConfigurableButton()) {
                    this.createConfigurableButton().visible(false);
                }
            } else {
                this.content(this.content1);

                if (this.createConfigurableButton()) {
                    this.createConfigurableButton().visible(true);
                }
            }
        }
    });
});
9
  • Will your code validate fields also?
    – Rushvi
    Commented Jul 28, 2016 at 6:04
  • yes my code validate fields. Commented Jul 28, 2016 at 6:15
  • ok Thanks. I will check and will let you know.
    – Rushvi
    Commented Jul 28, 2016 at 7:06
  • Its working fine Commented Feb 7, 2017 at 4:43
  • I have used above logic and it works fine with Magento 2.1.x version but it is not working with Magento2.2 version. Please provide me soluton.
    – Ajay
    Commented Oct 28, 2017 at 9:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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