I want to add a custom tab in catalog_product_edit
page with my custom module. I want this tab of ajax type, since the tab holds grid content.
To achieve this I rewrite the Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php
block with my Mysite/Combooffers/Block/Adminhtml/Catalog/Product/Edit/Tabs.php
block. It successfully rewrote the core block. My custom tab appeared in the edit page, but while click on the tab, it didnt work properly.
I have gone through the core files, and I found that, for ajax tabs, the action is defined in the controller Mage/Adminhtml/controllers/Catalog/ProductController.php
. So I assumed the problem occurs due to my tabs action is not present in the core controller. So I planned to rewrite the above controller with myown Mysite/Combooffers/controllers/Adminhtml/Catalog/ProductController.php
. When I rewrote the controller, edit page now shows nothing.
my app/code/local/Mysite/Combooffers/etc/config.xml
<config>
<modules>
<Mysite_Combooffers>
<version>0.1.0</version>
</Mysite_Combooffers>
</modules>
<frontend>
<routers>
<Combooffers>
<use>standard</use>
<args>
<module>Mysite_Combooffers</module>
<frontName>combooffers</frontName>
</args>
</Combooffers>
</routers>
<layout>
<updates>
<combooffers>
<file>combooffers.xml</file>
</combooffers>
</updates>
</layout>
</frontend>
<admin>
<routers>
<adminhtml>
<args>
<modules>
<Mysite_Combooffers before="Mage_Adminhtml">Mysite_Combooffers_Adminhtml</Mysite_Combooffers>
</modules>
</args>
</adminhtml>
</routers>
</admin>
<adminhtml>
<layout>
<updates>
<combooffers>
<file>combooffers.xml</file>
</combooffers>
</updates>
</layout>
</adminhtml>
<global>
<blocks>
<combooffers>
<class>Mysite_Combooffers_Block</class>
<sort_order>200</sort_order>
</combooffers>
<adminhtml>
<rewrite>
<catalog_product_edit_tabs>
Mysite_Combooffers_Block_Adminhtml_Catalog_Product_Edit_Tabs
</catalog_product_edit_tabs>
</rewrite>
</adminhtml>
</blocks>
<routers>
<adminhtml>
<rewrite>
<mysite_combooffers_adminhtml_catalog_product>
<from><![CDATA[#^admin/catalog_product/$#]]></from>
<to>/admin/catalog_product/</to>
</mysite_combooffers_adminhtml_catalog_product>
</rewrite>
</adminhtml>
</routers>
<helpers>
<combooffers>
<class>Mysite_Combooffers_Helper</class>
</combooffers>
</helpers>
</global>
</config>
app/code/local/Mysite/Combooffers/Block/Adminhtml/Catalog/Product/Edit/Tabs.php
<?php
class Mysite_Combooffers_Block_Adminhtml_Catalog_Product_Edit_Tabs extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs
{
protected function _prepareLayout()
{
/**Loads our tab using ajax.
* ajax tab loads while click on the tab on edit page. Normally use to load grid content.
* its complex
* url is the important one. when click on the tab, it will search for action correspond to the url in the controller.
* here the action name should be `comboofferAction()`
*/
$this->addTab('combooffer', array(
'label' => Mage::helper('catalog')->__('Combo Products'),
'url' => $this->getUrl('*/*/combooffer', array('_current' => true)),
'class' => 'ajax',
'after' => 'crosssell', //this will set tab after cross-sell tab.
));
return parent::_prepareLayout();
}
}
app/code/local/Mysite/Combooffers/Block/Adminhtml/Catalog/Products/Edit/Tab/Combooffer.php
<?php
class Mysite_Combooffers_Block_Adminhtml_Catalog_Product_Edit_Tab_Combooffer extends Mage_Adminhtml_Block_Widget_Form
{
/**
* Set grid params
*
*/
public function __construct()
{
parent::__construct();
$this->setId('combo_offers_product_grid');
$this->setDefaultSort('entity_id');
$this->setUseAjax(true); // Using ajax grid is important
if ($this->_getProduct()->getId()) {
$this->setDefaultFilter(array('in_products'=>1)); // By default we have added a filter for the rows,
//that in_products value to be 1
}
// if ($this->isReadonly()) {
// $this->setFilterVisibility(false);
//}
$this->setSaveParametersInSession(false); //Dont save paramters in session or else it creates problems
}
/**
* Retirve currently edited product model
*
* @return Mage_Catalog_Model_Product
*/
protected function _getProduct()
{
return Mage::registry('current_product');
}
/**
* Add filter
*
* @param object $column
* @return Mysite_Combooffers_Adminhtml_Block_Catalog_Product_Edit_Tab_Combooffer
*/
protected function _addColumnFilterToCollection($column)
{
// Set custom filter for in product flag
if ($column->getId() == 'in_products') {
$productIds = $this->_getSelectedComboOffers();
if (empty($productIds)) {
$productIds = 0;
}
if ($column->getFilter()->getValue()) {
$this->getCollection()->addFieldToFilter('entity_id', array('in'=>$productIds));
} else {
if($productIds) {
$this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds));
}
}
} else {
parent::_addColumnFilterToCollection($column);
}
return $this;
}
/**
* Prepare collection
*
* @return Mage_Adminhtml_Block_Widget_Grid
*/
protected function _prepareCollection()
{
$collection = Mage::getModel('catalog/product_link')->useUpSellLinks()
->getProductCollection()
->setProduct($this->_getProduct())
->addAttributeToSelect('*');
if ($this->isReadonly()) {
$productIds = $this->_getSelectedProducts();
if (empty($productIds)) {
$productIds = array(0);
}
$collection->addFieldToFilter('entity_id', array('in'=>$productIds));
}
$this->setCollection($collection);
return parent::_prepareCollection();
}
/**
* Add columns to grid
*
* @return Mage_Adminhtml_Block_Widget_Grid
*/
protected function _prepareColumns()
{
if (!$this->_getProduct()->getUpsellReadonly()) {
$this->addColumn('in_products', array(
'header_css_class' => 'a-center',
'type' => 'checkbox',
'name' => 'in_products',
'values' => $this->_getSelectedComboOffers(),
'align' => 'center',
'index' => 'entity_id'
));
}
$this->addColumn('entity_id', array(
'header' => Mage::helper('catalog')->__('ID'),
'sortable' => true,
'width' => 60,
'index' => 'entity_id'
));
$this->addColumn('name', array(
'header' => Mage::helper('catalog')->__('Name'),
'index' => 'name'
));
$this->addColumn('type', array(
'header' => Mage::helper('catalog')->__('Type'),
'width' => 100,
'index' => 'type_id',
'type' => 'options',
'options' => Mage::getSingleton('catalog/product_type')->getOptionArray(),
));
$sets = Mage::getResourceModel('eav/entity_attribute_set_collection')
->setEntityTypeFilter(Mage::getModel('catalog/product')->getResource()->getTypeId())
->load()
->toOptionHash();
$this->addColumn('set_name', array(
'header' => Mage::helper('catalog')->__('Attrib. Set Name'),
'width' => 130,
'index' => 'attribute_set_id',
'type' => 'options',
'options' => $sets,
));
$this->addColumn('status', array(
'header' => Mage::helper('catalog')->__('Status'),
'width' => 90,
'index' => 'status',
'type' => 'options',
'options' => Mage::getSingleton('catalog/product_status')->getOptionArray(),
));
$this->addColumn('visibility', array(
'header' => Mage::helper('catalog')->__('Visibility'),
'width' => 90,
'index' => 'visibility',
'type' => 'options',
'options' => Mage::getSingleton('catalog/product_visibility')->getOptionArray(),
));
$this->addColumn('sku', array(
'header' => Mage::helper('catalog')->__('SKU'),
'width' => 80,
'index' => 'sku'
));
$this->addColumn('price', array(
'header' => Mage::helper('catalog')->__('Price'),
'type' => 'currency',
'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE),
'index' => 'price'
));
$this->addColumn('position', array(
'header' => Mage::helper('catalog')->__('Position'),
'name' => 'position',
'type' => 'number',
'width' => 60,
'validate_class' => 'validate-number',
'index' => 'position',
'editable' => true, //!$this->_getProduct()->getUpsellReadonly(),
'edit_only' => true //!$this->_getProduct()->getId()
));
return parent::_prepareColumns();
}
/**
* Rerieve grid URL
*
* @return string
*/
public function getGridUrl()
{
return $this->_getData('grid_url') ? $this->_getData('grid_url') : $this->getUrl('*/*/combooffer', array('_current'=>true));
}
/**
* Retrieve selected combo offers
*
* @return array
*/
protected function _getSelectedComboOffers()
{
$products = $this->getSelectedComboOffers();
if (!is_array($products)) {
$products = array_keys($this->getSelectedComboOffers());
}
return $products;
}
/**
* Retrieve combo offers
*
* @return arraygetSelectedComboOffers
*/
public function getSelectedComboOffers()
{
$products = array();
foreach (Mage::registry('current_product')->getUpSellProducts() as $product) {
$products[$product->getId()] = array('position' => $product->getPosition());
}
return $products;
}
}
app/code/local/Mysite/Combooffers/controllers/Adminhtml/Catalog/ProductController.php
<?php
require_once('Mage/Adminhtml/controllers/Catalog/ProductController.php');
class Mysite_Combooffers_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Catalog_ProductController
{
/** Use to set content of combo offer tab.
* Defines layout of combo offer tab.
* The layout defined here should present in app/design/adminhtml/default/default/<layout>.xml
*/
public function comboofferAction()
{
$this->_initProduct();
$this->loadLayout();
$this->getLayout()->getBlock('catalog.product.edit.tab.combooffer')
->setProductsUpsell($this->getRequest()->getPost('products_combooffer', null));
$this->renderLayout();
}
}
app/design/adminhtml/default/default/layout/combooffers.xml
<combooffers_adminhtml_combooffer_combooffer>
<adminhtml_catalog_product_upsell>
<block type="core/text_list" name="root" output="toHtml">
<block type="adminhtml/catalog_product_edit_tab_upsell" name="catalog.product.edit.tab.combooffer"/>
<block type="adminhtml/widget_grid_serializer" name="upsell_grid_serializer">
<reference name="upsell_grid_serializer">
<action method="initSerializerBlock">
<grid_block_name>catalog.product.edit.tab.combooffer</grid_block_name>
<data_callback>getSelectedComboOffers</data_callback>
<hidden_input_name>links[combooffers]</hidden_input_name>
<reload_param_name>products_combooffer</reload_param_name>
</action>
<action method="addColumnInputName">
<input_name>position</input_name>
</action>
</reference>
</block>
</block>
</adminhtml_catalog_product_upsell>
</combooffers_adminhtml_combooffer_combooffer>
Is there any problem with my approach ? Am I in the right path? What is the error that I have made here? Please give your suggestions. Thanks in advance
Best Answer
It would be easier if you'd change url for ajax call on tab In
url
key is creating the path for ajax call. Asteriks means to use the same as current, so*/*/combooffer
is translated toadmin/catalog_product/combooffer
. You can change it to*/my_controller/combooffer
and it should work.So change file
app/code/local/Mysite/Combooffers/controllers/Adminhtml/Catalog/ProductController.php
toapp/code/local/Mysite/Combooffers/controllers/Adminhtml/Catalog/ComboofferController.php
so it would not overwrite core controller and make it extendMage_Adminhtml_Controller_Action
and in
app/code/local/Mysite/Combooffers/Block/Adminhtml/Catalog/Product/Edit/Tabs.php
use code:'url' => $this->getUrl('*/catalog_combooffer/combooffer', array('_current' => true)),