1

I have created one custom module and through that module, I want to add a custom button in Admin product edit form.

I have created a plugin using the below reference How to Add a Custom Button to Admin Sales Order View in Magento2

di.xml

    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="\Magento\Catalog\Block\Adminhtml\Product\Edit">
            <plugin name="Company_Module::pluginBeforeView" type="Company\Module\Plugin\PluginBeforeView" />
        </type>
    </config>

PluginBeforeView.php

namespace Company\Module\Plugin;

class PluginBeforeView
    {

        public function beforeGetOrderId(\Magento\Catalog\Block\Adminhtml\Product\Edit $subject){
            $subject->addButton(
                    'mybutton',
                    ['label' => __('My Buttion'), 'onclick' => 'setLocation(window.location.href)', 'class' => 'reset'],
                    -1
                );

            return null;
        }

    }

But it did not work. Any idea how to solve this.

2

2 Answers 2

9

The product form is generated via ui-components.
The ui component name for product form is view/adminhtml/ui_component/product_form.xml.

You need to create a file with the same name and path in your own module with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<form 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="buttons" xsi:type="array">
            <item name="button-unique-identifier-here" xsi:type="string">[Namespace]\[Module]\Block\Adminhtml\Product\Edit\Button\CustomButton</item>
        </item>
    </argument>
</form>

Then create the class [Namespace]\[Module]\Block\Adminhtml\Product\Edit\Button\CustomButton in the file [Namespace]/[Module]/Block/Adminhtml/Product/Edit/Button/CustomButton.php

<?php 
namespace [Namespace]\[Module]\Block\Adminhtml\Product\Edit\Button;

use Magento\Customer\Block\Adminhtml\Edit\GenericButton;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class CustomButton extends GenericButton implements ButtonProviderInterface
{
    public function getButtonData()
    {
        return [
            'label' => __('Your button label here'),
            'on_click' => "alert('it works')",
            'sort_order' => 100
        ];
    }
}

Your ui component file should be merged with the main file and your buttons should appear among the other buttons.

6
  • Hi Marius, thanks for the answer. But it didn't worked. I have created file product_form.xml under ui_component and CustomButton under CompanyName\ModuleName\Block\Adminhtml\Product\Edit\Button
    – Nitz
    Sep 28, 2016 at 10:05
  • I just tested it and it works like a charm. I needed to clean my Magento cache first however.
    – Pronto
    Jan 19, 2017 at 12:45
  • How can i give my controller action in on_click section
    – Pawankumar
    Feb 15, 2017 at 12:17
  • it worked great. Dec 28, 2017 at 7:09
  • It works, but it also showing on product creation page. How to show to product edit page only? Thanks
    – fmineo
    Jun 17, 2019 at 8:11
5

I wanted to add a custom button on customers info page in Magento admin but didn't find any related stuff except this helpful thread. Sharing my findings and code customization here.

Customer edit form buttons are defined in vendor/magento/module-customer/view/base/ui_component/customer_form.xml as

<item name="buttons" xsi:type="array">
    <item name="back" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\BackButton</item>
    <item name="delete" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\DeleteButton</item>
    <item name="invalidateToken" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\InvalidateTokenButton</item>
    <item name="unlock" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\UnlockButton</item>
    <item name="resetPassword" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetPasswordButton</item>
    <item name="order" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\OrderButton</item>
    <item name="reset" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetButton</item>
    <item name="save" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveButton</item>
    <item name="save_and_continue" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveAndContinueButton</item>
</item>

Every button has its own Block class.

So to add a new button, we need to extend customer_form.xml. Here are the steps:

Step 1: Create a customer edit form at Vendor\Module\view\base\ui_component\customer_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form 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="buttons" xsi:type="array">
            <item name="custom_button" xsi:type="string">Vendor\Module\Block\Adminhtml\Edit\Button\CustomButton</item>
        </item>
    </argument>
</form>

Step 2: Create a block class to render button at Vendor\Module\Block\Adminhtml\Edit\Button\CustomButton.php

<?php

namespace Vendor\Module\Block\Adminhtml\Edit\Button;

use Magento\Customer\Block\Adminhtml\Edit\GenericButton;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class CustomButton extends GenericButton implements ButtonProviderInterface {

    protected $_customerRepository;

    /**
     * @var AccountManagementInterface
     */
    protected $customerAccountManagement;

    /**
     * Constructor
     *
     * @param \Magento\Backend\Block\Widget\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param AccountManagementInterface $customerAccountManagement
     */
    public function __construct(
        \Magento\Backend\Block\Widget\Context               $context,
        \Magento\Framework\Registry                         $registry,
        \Magento\Customer\Api\AccountManagementInterface    $customerAccountManagement,
        \Magento\Customer\Api\CustomerRepositoryInterface   $customerRepository
    ) {
        parent::__construct($context, $registry);
        $this->customerAccountManagement    = $customerAccountManagement;
        $this->_customerRepository          = $customerRepository;
    }

    public function getButtonData()
    {
        $customerId = $this->getCustomerId();

        // get customer
        $customer = $this->_customerRepository->getById($customerId);

        // confirm message
        $message = __('Are you sure you want to do this?');

        if ($customer->getConfirmation())
        {
            return [
                'label' => __('Custom Button'),
                'on_click' => "confirmSetLocation('{$message}', '{$this->getCustomUrl()}')",
                //'on_click' => "alert('Hello')",
                'sort_order' => 100
            ];
        }

        return;
    }

    /**
     * URL getter
     *
     * @return string
     */
    public function getCustomUrl()
    {
        return $this->getUrl('custom/index/custom', ['customer_id' => $this->getCustomerId()]);
    }
}

Step 3: flush / clean cache and check if Admin panel is showing your custom button on Customer edit form.

Use 'on_click' => "alert('Hello')" just to ensure that your button is working. Then replace it with 'on_click' => "confirmSetLocation('{$message}', '{$this->getCustomUrl()}')",

Step 4: Create a route for controller action at: Vendor\Module\etc\adminhtml\routes.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="custom" frontName="custom">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

Step 5: Now define your controller action to perform something on button click. Controller path is Vendor\Module\Controller\Adminhtml\Index\Custom.php

<?php

namespace Vendor\Module\Controller\Adminhtml\Index;

use Magento\Integration\Api\CustomerTokenServiceInterface;
use Magento\Customer\Api\AccountManagementInterface;
use Magento\Customer\Api\AddressRepositoryInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Api\Data\AddressInterfaceFactory;
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
use Magento\Customer\Model\Address\Mapper;
use Magento\Framework\DataObjectFactory;
use Magento\Framework\Api\DataObjectHelper;

class Custom extends \Magento\Customer\Controller\Adminhtml\Index
{
    protected $_accountManagement;
    protected $_customerRepository;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
     * @param \Magento\Customer\Model\AddressFactory $addressFactory
     * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory
     * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
     * @param \Magento\Customer\Helper\View $viewHelper
     * @param \Magento\Framework\Math\Random $random
     * @param CustomerRepositoryInterface $customerRepository
     * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
     * @param Mapper $addressMapper
     * @param AccountManagementInterface $customerAccountManagement
     * @param AddressRepositoryInterface $addressRepository
     * @param CustomerInterfaceFactory $customerDataFactory
     * @param AddressInterfaceFactory $addressDataFactory
     * @param \Magento\Customer\Model\Customer\Mapper $customerMapper
     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
     * @param DataObjectHelper $dataObjectHelper
     * @param DataObjectFactory $objectFactory
     * @param \Magento\Framework\View\LayoutFactory $layoutFactory
     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
     *
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
        \Magento\Customer\Model\CustomerFactory $customerFactory,
        \Magento\Customer\Model\AddressFactory $addressFactory,
        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
        \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory,
        \Magento\Customer\Helper\View $viewHelper,
        \Magento\Framework\Math\Random $random,
        CustomerRepositoryInterface $customerRepository,
        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
        Mapper $addressMapper,
        AccountManagementInterface $customerAccountManagement,
        AddressRepositoryInterface $addressRepository,
        CustomerInterfaceFactory $customerDataFactory,
        AddressInterfaceFactory $addressDataFactory,
        \Magento\Customer\Model\Customer\Mapper $customerMapper,
        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
        DataObjectHelper $dataObjectHelper,
        DataObjectFactory $objectFactory,
        \Magento\Framework\View\LayoutFactory $layoutFactory,
        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
    ) {
        $this->_accountManagement   = $customerAccountManagement;
        $this->_customerRepository  = $customerRepository;
        parent::__construct(
            $context,
            $coreRegistry,
            $fileFactory,
            $customerFactory,
            $addressFactory,
            $formFactory,
            $subscriberFactory,
            $viewHelper,
            $random,
            $customerRepository,
            $extensibleDataObjectConverter,
            $addressMapper,
            $customerAccountManagement,
            $addressRepository,
            $customerDataFactory,
            $addressDataFactory,
            $customerMapper,
            $dataObjectProcessor,
            $dataObjectHelper,
            $objectFactory,
            $layoutFactory,
            $resultLayoutFactory,
            $resultPageFactory,
            $resultForwardFactory,
            $resultJsonFactory
        );
    }

    /**
     * custom action handler
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     */
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($customerId = $this->getRequest()->getParam('customer_id')) {
            try {

                // get customer
                $customer = $this->_customerRepository->getById($customerId);

                // do something here
                // put your code here

                // add message
                $this->messageManager->addSuccess(__('You have done this.'));

                // redirect
                $resultRedirect->setPath('customer/index/edit', ['id' => $customerId, '_current' => true]);
            } catch (\Exception $e) {
                $this->messageManager->addError($e->getMessage());
                $resultRedirect->setPath('customer/index/edit', ['id' => $customerId, '_current' => true]);
            }
        } else {
            $this->messageManager->addError(__('We can\'t find a customer to perform this action'));
            $resultRedirect->setPath('customer/index/index');
        }
        return $resultRedirect;
    }
}

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.