Magento 2.4 – Add Custom Button to Order Detail

adminadminhtmlmagento2magento2.4sales-order

I am trying to add a custom button to the admin order detail page. With the code below the button shows up correctly. However, when clicked the page loads to a 404 page. I can't seem to find a route configuration that makes it hit the correct route.

/app/code/MG/Dropship/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'MG_Dropship',
    __DIR__
);

/app/code/MG/Dropship/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="MG_Dropship" setup_version="1.0.0"/>
</config>

/app/code/MG/Dropship/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">
    <type name="Magento\Backend\Block\Widget\Button\Toolbar">
        <plugin name="addCustomButton" type="MG\Dropship\Plugin\Adminhtml\AddCustomButton" />
    </type>
</config>

/app/code/MG/Dropship/etc/adminhtml/routes.xml

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

/app/code/MG/Dropship/Controller/AdminHtml/Order/Index.php

<?php
namespace MG\Dropship\Controller\Adminhtml\Order;
 
class Index extends \Magento\Sales\Controller\Adminhtml\Order
{
    /**
     * Execute action
     *
     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
     */
    public function execute()
    {
        // In case you want to do something with the order
        $order = $this->_initOrder();
        $resultRedirect = $this->resultRedirectFactory->create();
        try {
            // TODO: Do something with the order
            $this->messageManager->addSuccessMessage(__('We did something!'));
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(__($e->getMessage()));
        }
 
        return $resultRedirect->setPath('sales/order/view', [ 'order_id' => $order->getId() ]);
    }
 
    /**
     * @return bool
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('MG_Dropship::order_dosomething');
    }
}

/app/code/MG/Dropship/Plugin/Adminhtml/AddCustomButton.php

<?php
namespace MG\Dropship\Plugin\Adminhtml;


class AddCustomButton
{
    /**
     * @param \Magento\Backend\Block\Widget\Button\Toolbar\Interceptor $subject
     * @param \Magento\Framework\View\Element\AbstractBlock $context
     * @param \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
     */
    public function beforePushButtons(
        \Magento\Backend\Block\Widget\Button\Toolbar\Interceptor $subject,
        \Magento\Framework\View\Element\AbstractBlock $context,
        \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
    )
    {
        if ($context->getRequest()->getFullActionName() == 'sales_order_view') {
            $url = $context->getUrl('mg_dropship/order/index');
            $buttonList->add(
                'customButton',
                ['label' => __('Do Something'), 'onclick' => 'setLocation("' . $url . '")', 'class' => 'reset'],
                -1
            );
        }
    }
}

For testing I've disabled 'Add Secret Key to URLs' in Stores > Settings > Configuration > Advanced > Admin > Security

It would be great if that could be enabled and work with this code.

Any help is greatly appreciated.

Best Answer

Update Plugin and Controller as below

 <?php
    namespace MG\Dropship\Plugin\Adminhtml;
    
    
    class AddCustomButton
    {
        /**
         * @param \Magento\Backend\Block\Widget\Button\Toolbar\Interceptor $subject
         * @param \Magento\Framework\View\Element\AbstractBlock $context
         * @param \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
         */
        public function beforePushButtons(
            \Magento\Backend\Block\Widget\Button\Toolbar\Interceptor $subject,
            \Magento\Framework\View\Element\AbstractBlock $context,
            \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
        )
        {
            if ($context->getRequest()->getFullActionName() == 'sales_order_view') {
                $order_id = $context->getRequest()->getParam('order_id');
                $url = $context->getUrl('mg_dropship/order/index', ['order_id' => $order_id]);
                $buttonList->add(
                    'customButton',
                    ['label' => __('Do Something'), 'onclick' => 'setLocation("' . $url . '")', 'class' => 'reset'],
                    -1
                );
            }
        }
    }


****/app/code/MG/Dropship/Controller/AdminHtml/Order/Index.php****


<?php
namespace MG\Dropship\Controller\Adminhtml\Order;
 
class Index extends \Magento\Sales\Controller\Adminhtml\Order
{
    /**
     * Execute action
     *
     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
     */
    public function execute()
    {   
        // In case you want to do something with the order
        $order_id = $this->getRequest()->getParam('order_id');
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $order = $objectManager->create('\Magento\Sales\Model\Order')
                           ->load($order_id); 
        //$order = $this->_initOrder();
        $resultRedirect = $this->resultRedirectFactory->create();
        try {
            // TODO: Do something with the order
            $this->messageManager->addSuccessMessage(__('We did something!'));
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(__($e->getMessage()));
        }
 
        return $resultRedirect->setPath('sales/order/view', [ 'order_id' => $order->getId() ]);
    }
 
    /**
     * @return bool
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('MG_Dropship::order_dosomething');
    }
}