Sometimes Magento still confuses me when I try to create adminhtml pages and widgets like tabs or grids. One interesting example is that I needed a grid inside an edit form for a one-to-many relationship - just like how the coupons form and grid is located inside of a shopping cart pricerule.
In this article I’ll explain some of Magento’s most common adminhtml blocks and how they can be used.
Introducing the adminhtml blocks
Mage_Adminhtml_Block_Template
: pretty much the same as the normal template block, except it contains a method to get the formkey and throws the adminhtml_block_html_before
event. It's extended by most blocks I'm going to describe.
Mage_Adminhtml_Block_Widget
: generic widget class. Contains various methods for generating HTML for buttons and icons.
Mage_Adminhtml_Block_Widget_Container
: mostly contains logic for adding buttons.
Mage_Adminhtml_Block_Widget_Form
: Your class that extends it, is responsible for creating and containing your form (Varien_Data_Form
). The _prepareForm
method is where you set your form details such as enctype, method (post or get) and action.
Mage_Adminhtml_Block_Widget_Form_Container
: Adds the common buttons (back, save, etc) and adds a varienForm javascript object for validation. Extends Mage_Adminhtml_Block_Widget_Container
.
Mage_Adminhtml_Block_Widget_Grid
: Renders a grid which you can pass a collection of models to. Automatically handles filtering and searching.
Mage_Adminhtml_Block_Widget_Grid_Container
:
Adds a header and footer to your grid, and creates the “Add” button. Also extends Mage_Adminhtml_Block_Widget_Container
.
Mage_Adminhtml_Block_Widget_Tabs
:
When this block is in content
, the layout switches to something similar to a col2-left layout with tabs on the left side. Contains logic for adding/removing tabs.
Mage_Adminhtml_Block_Widget_Tab_Interface
:
Interface for any blocks that can be used as tabs. Has methods such as getTabLabel
and canShowTab
Any block can implement this interface. The normal _toHtml
method is used to render the tab content. Usually you will see Widget Forms or Text List blocks implementing this interface.
Layout and block order
Now you know what the main blocks are, let's look at how an avarage layout xml of an adminhtml page looks like.
<!-- Handle for editing Shopping Cart Price Rules -->
<adminhtml_promo_quote_edit>
<!-- ... -->
<reference name="left">
<!-- block is an instance of Mage_Adminhtml_Block_Widget_Tabs -->
<block type="adminhtml/promo_quote_edit_tabs">
<!-- instance of Mage_Adminhtml_Block_Widget_Form -->
<block type="adminhtml/promo_quote_edit_tab_main" />
<!-- instance of Mage_Adminhtml_Block_Text_List -->
<block type="adminhtml/promo_quote_edit_tab_coupons">
<!-- instance of Mage_Adminhtml_Block_Widget_Form -->
<block
type="adminhtml/promo_quote_edit_tab_coupons_form"
name="promo_quote_edit_tab_coupons_form"/>
<!-- instance of Mage_Adminhtml_Block_Widget_Grid -->
<block
type="adminhtml/promo_quote_edit_tab_coupons_grid"
name="promo_quote_edit_tab_coupons_grid"/>
</block>
<!-- following two methods add the previous two blocks to the tabs -->
<action method="addTab">
<name>main_section</name>
<block>promo_quote_edit_tab_main</block>
</action>
<action method="addTab">
<name>coupons_section</name>
<block>promo_quote_edit_tab_coupons</block>
</action>
</block>
<!-- Some javascript to make the coupon generator form work -->
<block type="adminhtml/template"
template="promo/salesrulejs.phtml"/>
</reference>
<reference name="content">
<!-- Mage_Adminhtml_Block_Widget_Form_Container -->
<block type="adminhtml/promo_quote_edit"/>
</reference>
</adminhtml_promo_quote_edit>
Note: I've removed the names of the blocks for simplicity.
Notable is that content
contains the form container, even though all the other forms are rendered inside left.
Also cool is that the coupons grid and generate coupons form can be inside a form. This structure is handy for models that have a one to many relationship. In this case, a rule can have multiple coupons. Keep in mind though that when you have this structure, the input’s of the grid column filtering will be part of the data you submit. To avoid id conflicts, you have to give the columns a different id.
This should give you a slightly better idea on how to construct adminhtml pages. And remember to always look at the core code for the specific implementation details, as Magento lacks good documentation.