Magento core has all the example you need.
Look at how the salesrules adminhtml is built. It is a good example of how tabs can be built using layout.xml
You just need to systematically duplicate the structure into your own module, and you will have tabs, handled by layout.xml. It is then easy to add tabs as needed.
Here is a rundown:
Have a look at promo.xml in app/design/adminhtml/default/default/layout/promo.xml, specifically at the handle <adminhtml_promo_quote_edit>
Here you will find the layout that defines the tabs used in the promo rule section:
<reference name="left">
<block type="adminhtml/promo_quote_edit_tabs" name="promo_quote_edit_tabs">
<block type="adminhtml/promo_quote_edit_tab_main" name="promo_quote_edit_tab_main" />
<block type="adminhtml/promo_quote_edit_tab_conditions" name="promo_quote_edit_tab_conditions"/>
<block type="adminhtml/promo_quote_edit_tab_actions" name="promo_quote_edit_tab_actions"/>
<block type="adminhtml/promo_quote_edit_tab_labels" name="promo_quote_edit_tab_labels"/>
<block type="adminhtml/promo_quote_edit_tab_coupons" name="promo_quote_edit_tab_coupons">
<block type="adminhtml/promo_quote_edit_tab_coupons_form" name="promo_quote_edit_tab_coupons_form"/>
<block type="adminhtml/promo_quote_edit_tab_coupons_grid" name="promo_quote_edit_tab_coupons_grid"/>
</block>
<action method="addTab"><name>main_section</name><block>promo_quote_edit_tab_main</block></action>
<action method="addTab"><name>conditions_section</name><block>promo_quote_edit_tab_conditions</block></action>
<action method="addTab"><name>actions_section</name><block>promo_quote_edit_tab_actions</block></action>
<action method="addTab"><name>labels_section</name><block>promo_quote_edit_tab_labels</block></action>
<action method="addTab"><name>coupons_section</name><block>promo_quote_edit_tab_coupons</block></action>
</block>
<block type="adminhtml/template" template="promo/salesrulejs.phtml" name="promo_quote_edit_jsinit"/>
</reference>
So, from the above you will find that you first define the main tabs container block:
<block type="adminhtml/promo_quote_edit_tabs" name="promo_quote_edit_tabs">
The block class definition is as such:
class Mage_Adminhtml_Block_Promo_Quote_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
which gives you the 'addTabs' functionality, as used in the layouts.
This is thus your starting point.
Next you define a block that will become a tab within this container.
In the example, the first block is <block type="adminhtml/promo_quote_edit_tab_main" name="promo_quote_edit_tab_main" />
and the class is defined as:
class Mage_Adminhtml_Block_Promo_Quote_Edit_Tab_Main
extends Mage_Adminhtml_Block_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
You then attach this block to the container using the addTab action
<action method="addTab"><name>main_section</name><block>promo_quote_edit_tab_main</block></action>
and repeat the process for each tab you add.
The coupons tab gives you a good example of how to place a grid within a tab.
I hope this pointer gets you in the right direction.
Ask for any further clarification.
This is the important part that appear in the given code part.
<?php foreach ($this->getTabs() as $_index => $_tab): ?>
<?php if($this->getChildHtml($_tab['alias'])): ?>
<div class="meigee-tabs-content" id="product_tabs_<?php echo $_tab['alias'] ?>_contents"><?php echo $this->getChildHtml($_tab['alias']) ?></div>
<?php endif; ?>
<?php endforeach; ?>
These are my findings. Template gets all the tabs by requesting $this->getTabs()
which will return an array that holds information about tabs. My guess is all those tabs are configured through layout XML files. Any ways this method provide an array some what looks like this.
array(
'index1' => array(
'alias' => 'alias_1',
'name' => 'name_1', //not sure
'title' => 'title_1'
.....
),
'index2' => array(
'alias' => 'alias_2',
'name' => 'name_2', //not sure
'title' => 'title_2'
.....
),
.....
)
So you have two options available
1. Inject your tab through Layout Update
You need to inject your block as other tabs included through layout XML. For this you need to find out which block that holds this template. You can see that tab blocks are included as its child block there. You need to put your custom block in the similar way default tabs are included. This will be the cleanest way to do that. But harder one
2. Forcefully inject your block via template file itself
This will be the easiest way to do this. For this you can use this concept.
<?php
//get tab array
$tabs = $this->getTabs();
//create an array for your tab
$my_tab = array(
'my_tab' => array(
'alias' => $this->getLayout()->createBlock('cms/block')->setBlockId($manu)->toHtml(),
'title' => 'Manufacturer'
));
//inject your block to tab array
array_merge($tabs, $my_tab);
?>
<!-- need some modification here -->
<ul class="meigee-tabs">
<?php foreach ($tabs as $_index => $_tab): ?>
<?php if($_index != 'my_tab') : ?>
<?php if($this->getChildHtml($_tab['alias'])): ?>
<li id="product_tabs_<?php echo $_tab['alias'] ?>" class="<?php echo !$_index?' active first':''?>"><a href="#"><?php echo $_tab['title']?></a></li>
<?php endif; ?>
<?php else : ?>
<li id="product_tabs_manufacturer" class="<?php echo !$_index?' active first':''?>"><a href="#"><?php echo $_tab['title']?></a></li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php foreach ($tabs as $_index => $_tab): ?>
<?php if($_index != 'my_tab') : ?>
<?php if($this->getChildHtml($_tab['alias'])): ?>
<div class="meigee-tabs-content" id="product_tabs_<?php echo $_tab['alias'] ?>_contents"><?php echo $this->getChildHtml($_tab['alias']) ?></div>
<?php endif; ?>
<?php else : ?>
<div class="meigee-tabs-content" id="product_tabs_manufacturer_contents"><?php echo $_tab['alias'] ?></div>
<?php endif; ?>
<?php endforeach; ?>
First we retrieve tab array and inject my own tab array as element in the parent tab array. Since we put the alias
with html of cms block(where as all other blocks holds a string for this alias
), we cannot use default way of rendering the name and content of other blocks. So we separate our custom array entry with an if statement logic
and changed those part according to our need(you can see those changes above).
Hope you get an idea how to do that. Let me know the result.
Best Answer
Try this, it's a bit funky but it works. The idea is to add new tab only if
sizes_table
is set on the current product instance.In your layout update file (
local.xml
):Custom block class (
app/code/local/Foo/Bar/Block/Block.php
):If the
Size Guide
tab is not added try commenting outif ($product->getData('sizes_table'))
condition. If it's added after that, you'll have to find another way to retrieve the product attribute.