How to add custom button to order view page near "Back" and "Edit"?
Asked
Active
Viewed 3.1k times
4 Answers
41
Instead of core hacks or rewrites, just use an observer to add the button to the order:
<adminhtml>
<events>
<adminhtml_widget_container_html_before>
<observers>
<your_module>
<class>your_module/observer</class>
<type>singleton</type>
<method>adminhtmlWidgetContainerHtmlBefore</method>
</your_module>
</observers>
</adminhtml_widget_container_html_before>
</events>
</adminhtml>
Then just check in the observer if the type of the block matches the order view:
public function adminhtmlWidgetContainerHtmlBefore($event)
{
$block = $event->getBlock();
if ($block instanceof Mage_Adminhtml_Block_Sales_Order_View) {
$message = Mage::helper('your_module')->__('Are you sure you want to do this?');
$block->addButton('do_something_crazy', array(
'label' => Mage::helper('your_module')->__('Export Order'),
'onclick' => "confirmSetLocation('{$message}', '{$block->getUrl('*/yourmodule/crazy')}')",
'class' => 'go'
));
}
}
The "getUrl" function of the block will automatically append the current order id to the controller call.

Matthias Kleine
- 1,228
- 17
- 15
-
1no class rewrite, no corefile changed - awesome solution, I can confirm it works at least in 1.8 – simonthesorcerer May 19 '15 at 10:14
-
2This is a MUCH better answer. Answers that require subclassing to override the default Magento classes like this will cause lots of problems with extension conflicts and upgrade incompatibilities. If Magento has a method using an Observer, it is usually the approach. – Phil M Jun 15 '15 at 16:14
23
config.xml:
<global>
<blocks>
<adminhtml>
<rewrite>
<sales_order_view>Namespace_Module_Block_Adminhtml_Sales_Order_View</sales_order_view>
</rewrite>
</adminhtml>
</blocks>
</global>
Namespace/Module/Block/Adminhtml/Sales/Order/View.php:
class Namespace_Module_Block_Adminhtml_Sales_Order_View extends Mage_Adminhtml_Block_Sales_Order_View {
public function __construct() {
parent::__construct();
$this->_addButton('button_id', array(
'label' => Mage::helper('xxx')->__('Some action'),
'onclick' => 'jsfunction(this.id)',
'class' => 'go'
), 0, 100, 'header', 'header');
}
}

Alex Rashkov
- 9,833
- 3
- 32
- 58

silex
- 4,312
- 4
- 22
- 27
-
3an example for the 'onclick' method is "confirmSetLocation('{$message}', '{$this->getOkToShipUrl()}')", – Jonathan Day Oct 24 '11 at 23:00
-
needed to call parent::__construct(); in your custom __construct() function, or I would get "Invalid block type" exception. – James Mar 08 '12 at 20:36
-
I'm getting an error when implementing this. @james what did you mean by the parent::__construct? – Tom Mar 25 '12 at 17:03
-
-
4Please use an observer instead of adding a rewrite to such an important core class. With this solution you can get trouble with other extensions and the rewrite is not necessary to achieve this! – Matthias Kleine Feb 02 '15 at 12:06
2
In reference to the comments above about the parent::__constructor, here is what worked for me:
class Name_Module_Block_Adminhtml_Sales_Order_View extends Mage_Adminhtml_Block_Sales_Order_View {
public function __construct() {
$this->_addButton('testbutton', array(
'label' => Mage::helper('Sales')->__('Toms Button'),
'onclick' => 'jsfunction(this.id)',
'class' => 'go'
), 0, 100, 'header', 'header');
parent::__construct();
}
}

Tom
- 427
- 6
- 27
-
you should do something like $return = parent::__construct(); at the beginning of the function, do your thing and then return $return; at the end. – Gabriel Queiroz Silva Jul 23 '14 at 00:12
-
1@GabrielQueirozSilva Constructors have no return values. This is a correct answer. – Matthias Kleine Jun 23 '15 at 07:43
-
@MatthiasKleine ops, hadn't noticed it was a constructor. – Gabriel Queiroz Silva Jun 26 '15 at 16:32
-2
If you want to do it quick-and-dirty (i.e. editing core files), open app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php
and add something like:
$this->_addButton('order_reorder', array(
'label' => Mage::helper('sales')->__('Print Labels'),
'onclick' => 'window.open(\'/printouts/' . $this->getOrder()->getRealOrderId() . '.pdf\')',
));
You can place that before this block:
if ($this->_isAllowedAction('emails') && !$order->isCanceled()) {
$message = Mage::helper('sales')->__('Are you sure you want to send order email to customer?');
$this->addButton('send_notification', array(
'label' => Mage::helper('sales')->__('Send Email'),
'onclick' => "confirmSetLocation('{$message}', '{$this->getEmailUrl()}')",
));
}
Your challenge, should you choose to accept is to create a file in local that is an over-ride of the core file, and to post it here!

ʍǝɥʇɐɯ
- 4,012
- 7
- 32
- 53
-
8Worst answer - do not modify core files in any situation. Never. Easy. No quick and dirty - keep clean coding! – Matthias Kleine Feb 02 '15 at 12:03