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 ?

  • Hello, I am doing something kind of same. Did you get the way? Kindly update the ans if you have. Thanks in Advance!! – Rushvi Jul 28 '16 at 5:19
  • Thanks Jaimin, today it helps me a lot to resolve issue :) +5 from me – Keyur Shah Jan 19 '17 at 12:39
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);
                }
            }
        }
    });
});
| improve this answer | |
  • Will your code validate fields also? – Rushvi Jul 28 '16 at 6:04
  • yes my code validate fields. – Jaimin Parikh Jul 28 '16 at 6:15
  • ok Thanks. I will check and will let you know. – Rushvi Jul 28 '16 at 7:06
  • Its working fine – Jalpesh Patel Feb 7 '17 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 Oct 28 '17 at 9:27

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.