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;
}
}