It is sometimes required to add buttons at the top of admin forms. The easy-but-not-so-good solution is to make a rewrite. The easy-and-good-trick elegant solution is to use an observer. Here is an example for the product edit page.
The trick in a nutshell
The idea is to:
- Create a container of
core/text_list
type - Inject the content of the original Magento "Save and Continue Edit" button
- Inject the content of our new button
- Remplace the content of the original Magento "Save and Continue Edit" button by this container
- The block of the "Save and Continue Edit" button will then be a
core/text_list
block containing both the original button and our new one
Making things happen
As a pre-requisit, a module must exist (in our example, this module is Herve_ProductEditButton
) with:
- Its declaration file (
etc/modules/Herve_ProductEditButton.xml)
- Its configuration file (
app/code/community/Herve/Herve_ProductEditButton/etc/config.xml
) - An admin controller (
app/code/community/Herve/Herve_ProductEditButton/controllers/Adminhtml/ButtonController.php
) - A
Helper
in order to manage translations (app/code/community/Herve/Herve_ProductEditButton/Helper/Data.php
). Translations have not been done for this example
An observer (app/code/community/Herve/Herve_ProductEditButton/Model/Observer.php
)
We will then observe the controller_action_layout_render_before_adminhtml_catalog_product_edit
event for the adminthml
area. The goal is to retrieve the layout right before it is planed to be rendered as HTML and inject our modifications.
The observer is declared like this:
<config>
...
<adminhtml>
<events>
<controller_action_layout_render_before_adminhtml_catalog_product_edit>
<observers>
<herve_producteditbutton_add_button>
<class>Herve_ProductEditButton_Model_Observer</class>
<method>addButton</method>
</herve_producteditbutton_add_button>
</observers>
</controller_action_layout_render_before_adminhtml_catalog_product_edit>
</events>
</adminhtml>
...
</config>
We must then implement the observer. Here is its commented code:
class Herve_ProductEditButton_Model_Observer
{
/**
* Add a new button next to the existing "Save and Continue Edit" button
*
* @return void
*/
public function addButton()
{
// Retrieve layout
$layout = Mage::app()->getLayout();
// Retrieve product_edit block
$productEditBlock = $layout->getBlock('product_edit');
// Retrieve original "Save and Continue Edit" button
$saveAndContinueButton = $productEditBlock->getChild('save_and_edit_button');
// Create new button
$myButton = $layout->createBlock('adminhtml/widget_button')
->setData(array(
'label' => Mage::helper('producteditbutton')->__('My Button Label'),
'onclick' => 'setLocation(\'' . $this->getButtonUrl() . '\')',
'class' => 'save'
));
// Create a container that will gather existing "Save and Continue Edit" button and the new button
$container = $layout->createBlock('core/text_list', 'button_container');
// Append existing "Save and Continue Edit" button and the new button to the container
$container->append($saveAndContinueButton);
$container->append($myButton);
// Replace the existing "Save and Continue Edit" button with our container
$productEditBlock->setChild('save_and_edit_button', $container);
}
/**
* Retrieve the URL for button click
*
* @return string
*/
public function getButtonUrl()
{
// The URL called fits to the controller of our module: Herve_ProductEditButton_Adminhtml_ButtonController
return Mage::getModel('adminhtml/url')->getUrl('*/button/myButton', array(
'_current' => true,
'back' => 'edit',
'tab' => '{{tab_id}}',
'active_tab' => null
));
}
}
We will then code the controller that is in charge of our new button's behavior. As we have generated an URL in the previous observer with the code Mage::getModel('adminhtml/url')->getUrl('*/button/myButton')
, the controller is then Herve_ProductEditButton_Adminhtml_ButtonController
and its action method is myButtonAction()
Here is the commented code of the controller:
class Herve_ProductEditButton_Adminhtml_ButtonController extends Mage_Adminhtml_Controller_Action
{
/**
* Behavior of our new button when it is clicked
*/
public function myButtonAction()
{
// Retrieve product id from which the button has been clicked
$productId = $this->getRequest()->getParam('id');
/**
*
* All custom controller logic goes here
*
*/
$this->_getSession()->addSuccess($this->__('Congratulations, you clicked on a button!'));
// Redirect to product edit page
$this->_redirect('*/catalog_product/edit', array(
'id' => $productId,
'_current'=>true
));
}
}
Results
As expected, there is a new button labeled "My Button Label" next to the "Save and Continue Edit" original button.

For other forms
The process is the same. What may be difficult is:
- to retrieve the "edit" block that embeds the button to by modified with the container (
product_edit
in our example) - to retrieve the block name of the button to by modified with the container (
save_and_edit_button
in our example)
Example module
An example module is available here: https://github.com/herveguetin/Herve_ProductEditButton