I am trying to add another tab to the category edit page that contains another product grid. I need to do this because i want to add to each category page a zone that contains the products that are selected in this grid.
Can anyone help me finish the module ? or is there a easier or existing module to do this ?
PS: Complete code is greatly appreciated :)
This is where i got so far: etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<Forideas_Promotion>
<version>0.1.0</version>
</Forideas_Promotion>
</modules>
<global>
<resources>
<forideas_promotion_setup>
<setup>
<module>Forideas_Promotion</module>
<class>Forideas_Promotion_Model_Resource_Setup</class>
</setup>
</forideas_promotion_setup>
</resources>
<helpers>
<promotion>
<class>Forideas_Promotion_Helper</class>
</promotion>
</helpers>
<models>
<forideas_promotion>
<class>Forideas_Promotion_Model</class>
</forideas_promotion>
<promotion_resource>
<entities>
<category_product>
<table>category_product</table>
</category_product>
</entities>
</promotion_resource>
</models>
<events>
<adminhtml_catalog_category_tabs>
<observers>
<forideas_promotion_observer>
<class>forideas_promotion/observer</class>
<method>addCategoryTab</method>
</forideas_promotion_observer>
</observers>
</adminhtml_catalog_category_tabs>
</events>
</global>
<adminhtml>
<layout>
<updates>
<forideas_category_promotion>
<file>forideas_promotion.xml</file>
</forideas_category_promotion>
</updates>
</layout>
</adminhtml>
<admin>
<routers>
<adminhtml>
<args>
<modules>
<Forideas_Promotion before="Mage_Adminhtml">Forideas_Promotion_Adminhtml</Forideas_Promotion>
</modules>
</args>
</adminhtml>
</routers>
</admin>
</config>
Block/Adminhtml/Category/Edit/Tab/Product.php:
<?php
class Forideas_Promotion_Block_Adminhtml_Category_Edit_Tab_Product
extends Mage_Adminhtml_Block_Widget_Grid {
public function __construct(){
parent::__construct();
$this->setId('product_grid');
$this->setDefaultSort('position');
$this->setDefaultDir('ASC');
$this->setUseAjax(true);
if ($this->getCategory()->getId()) {
$this->setDefaultFilter(array('in_products'=>1));
}
}
protected function _prepareCollection() {
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->addAttributeToSelect('price');
$adminStore = Mage_Core_Model_App::ADMIN_STORE_ID;
$collection->joinAttribute('product_name', 'catalog_product/name', 'entity_id', null, 'left', $adminStore);
if ($this->getCategory()->getId()){
$constraint = '{{table}}.category_id='.$this->getCategory()->getId();
}
else{
$constraint = '{{table}}.category_id=0';
}
$collection->joinField('position',
'promotion/category_product',
'position',
'product_id=entity_id',
$constraint,
'left');
$this->setCollection($collection);
parent::_prepareCollection();
return $this;
}
protected function _prepareMassaction(){
return $this;
}
protected function _prepareColumns(){
$this->addColumn('in_products', array(
'header_css_class' => 'a-center',
'type' => 'checkbox',
'name' => 'in_products',
'values'=> $this->_getSelectedProducts(),
'align' => 'center',
'index' => 'entity_id'
));
$this->addColumn('product_name', array(
'header'=> Mage::helper('catalog')->__('Name'),
'align' => 'left',
'index' => 'product_name',
));
$this->addColumn('sku', array(
'header'=> Mage::helper('catalog')->__('SKU'),
'align' => 'left',
'index' => 'sku',
));
$this->addColumn('price', array(
'header'=> Mage::helper('catalog')->__('Price'),
'type' => 'currency',
'width' => '1',
'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',
'width' => 60,
'type' => 'number',
'validate_class'=> 'validate-number',
'index' => 'position',
'editable' => true,
));
}
protected function _getSelectedProducts(){
$products = $this->getCategoryProducts();
if (!is_array($products)) {
$products = array_keys($this->getSelectedProducts());
}
return $products;
}
public function getSelectedProducts() {
$products = array();
$selected = Mage::registry('current_category')->getSelectedProducts();
if (!is_array($selected)){
$selected = array();
}
foreach ($selected as $product) {
$products[$product->getId()] = array('position' => $product->getPosition());
}
return $products;
}
public function getRowUrl($item){
return '#';
}
public function getGridUrl(){
return $this->getUrl('*/*/productsGrid', array(
'id'=>$this->getCategory()->getId()
));
}
public function getCategory(){
return Mage::registry('current_category');
}
protected function _addColumnFilterToCollection($column){
// Set custom filter for in product flag
if ($column->getId() == 'in_products') {
$productIds = $this->_getSelectedProducts();
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;
}
}
controllers/Adminhtml/Promotion/Category/ProductController.php:
<?php
require_once ("Mage/Adminhtml/controllers/Catalog/ProductController.php");
class Forideas_Promotion_Adminhtml_Promotion_Category_ProductController extends Mage_Adminhtml_Catalog_ProductController
{
public function productsAction(){
//$this->_initEntity(); //if you don't have such a method then replace it with something that will get you the entity you are editing.
$this->loadLayout();
$this->getLayout()->getBlock('category.edit.tab.product')
->setCategoryProducts($this->getRequest()->getPost('category_products', null));
$this->renderLayout();
}
public function productsgridAction(){
//$this->_initCategory();
$this->loadLayout();
$this->getLayout()->getBlock('category.edit.tab.product')
->setCategoryProducts($this->getRequest()->getPost('category_products', null));
$this->renderLayout();
}
}
Model/Observer.php
<?php
class Forideas_Promotion_Model_Observer{
public function addCategoryTab($observer)
{
$block = $observer->getEvent()->getTabs();
$block->addTab('features', array(
'label' => Mage::helper('catalog')->__('Some Label here'),
'url' => Mage::helper('adminhtml')->getUrl('adminhtml/promotion_category_product/productsgrid', array('_current' => true)),
'class' => 'ajax',
));
}
}
sql/setup/install-0.1.0.php
$this->startSetup();
$table = $this->getConnection()
->newTable($this->getTable('promotion/category_product'))
->addColumn('rel_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'identity' => true,
'nullable' => false,
'primary' => true,
), 'Relation ID')
->addColumn('category_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'nullable' => false,
'default' => '0',
), 'Category ID')
->addColumn('product_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'nullable' => false,
'default' => '0',
), 'Product ID')
->addColumn('position', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'nullable' => false,
'default' => '0',
), 'Position')
->addIndex($this->getIdxName('promotion/category_product', array('product_id')), array('product_id'))
->addForeignKey($this->getFkName('promotion/category_product', 'category_id', 'promotion/category', 'entity_id'), 'category_id', $this->getTable('promotion/category'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->addForeignKey($this->getFkName('promotion/category_product', 'product_id', 'catalog/product', 'entity_id'), 'product_id', $this->getTable('catalog/product'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->setComment('Category to Product Linkage Table');
$this->getConnection()->createTable($table);
$this->endSetup();
I found the answer to your 'ajax loader will not disappear' problem. This is due to the fact that the HTML that is returned from the AJAX call actually refers to the original table, catalog_category_products_table. But the Javascript is looking for your own table name but can't find it and thus the infinite Please wait loader.
The solution is to create your own controller that extends Mage_Adminhtml_Catalog_CategoryController and load your own block with your gridname there. Then, in the block where you extended Mage_Adminhtml_Block_Catalog_Category_Tab_Product, you will define getGridUrl() and return the path to your newly created controller. Now everything will just work fine.