Grid doesn't appear in custom admin module in Magento - magento

I am trying to create a custom module in magento admin. I have reached the point where a new link has been added to the menu and by clicking on it, I can navigate to the index action of the controller of the module. But here I cannot see the grid, only the header text and the button which has been added in the block construct appear.
I can see that since this block extends the Mage_Adminhtml_Block_Widget_Grid_Container class, it will by itself add the grid block inside this module as its child.
And the Grid.php is included which I verified by printing out something in the overriden _prepareColumns method.
What am I missing here ?
These are the contents of the Grid.php file
class Book_Brands_Block_Adminhtml_Brands_Grid extends Mage_Adminhtml_Block_Widget_Grid {
public function __construct() {
parent::__construct();
$this->setId('brandsGrid');
$this->setDefaultSort('brands_id');
$this->setDefaultDir('ASC');
$this->setSaveParametersInSession(true);
}
protected function _prepareCollection() {
$collection = Mage::getModel('brands/brands')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns() {
$this->addColumn('brands_id', array(
'header' => Mage::helper('brands')->__('ID'),
'align' =>'right',
'width' => '50px',
'index' => 'brands_id',
));
$this->addColumn('title', array(
'header'=> Mage::helper('brands')->__('Title'),
'align' =>'left',
'index' => 'title',
));
$this->addColumn('status', array(
'header'=> Mage::helper('brands')->__('Status'),
'align' => 'left',
'width' => '80px',
'index' => 'status',
'type' => 'options',
'options' => array(
1 => 'Enabled',
2 => 'Disabled',
),
));
$this->addColumn('action', array(
'header' => Mage::helper('brands')->__('Action'),
'width' => '100',
'type' => 'action',
'getter' => 'getId',
'actions' => array(
array(
'caption' => Mage::helper('brands')->__('Edit'),
'url' => array('base'=> '*/*/edit'),
'field' => 'id'
)
),
'filter' => false,
'sortable' => false,
'index' => 'stores',
'is_system' => true,
));
return parent::_prepareColumns();
}
public function getRowUrl($row) {
return $this->getUrl('*/*/edit', array('id' => $row->getId()));
}
}
Thanks
PS. I have tried flushing the cache but no luck

From memory I think _prepareColumns() is called before _prepareCollection() so if there is an error in the collection the grid won't get rendered even though you have confirmed the columns method.
Part of parent::_prepareCollection() tries to estimate the number of pages from the collection's getSize() and getSelectCountSql() methods, I often forget to check those are producing sane results which trips me up. Make sure all logging is turned on and put the following in your .htaccess file:
php_flag display_errors on
SetEnv MAGE_IS_DEVELOPER_MODE true
Try seeing what query is being generated with these commands:
Mage::log((string)$collection->getSelect());
Mage::log((string)$collection->getSelectCountSql());

Looks like you have the grid blocks set up correctly. However, you still need to load the grid into the layout and render it. This can either be done in the adminhtml layout xml or in the controller.
In your /app/design/adminhtml/../layout/brands.xml:
<?xml version="1.0"?>
<layout>
<brands_index_index>
<reference name="content">
<block type="brands/brands_grid" name="brands_grid"></block>
</reference>
</brands_index_index>
</layout>
In your controller:
public function indexAction()
{
$this->loadLayout();
$this->_addContent(
$this->getLayout()->createBlock('brands/brands_grid','brands')
);
$this->renderLayout();
}
Please note that you have to modify the above to your particular implementation. I think the layout xml is harder to comprehend initially than the programmatic instantiation in the controller, however, in the long run, it leads to less code bloat.

Just had a quick view and the only thing I can see in your code is:
protected function _prepareCollection() {
$collection = Mage::getModel('brands/brands')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
//Try to use it like this:
protected function _prepareCollection() {
$collection = Mage::getModel('brands/brands')->getCollection();
$this->setCollection($collection);
parent::_prepareCollection();
return $this;
}

Related

How to override _prepareCollection and _prepareColumns in Magento Admin

How to override _prepareCollection and _prepareColumn from core to local. I want to add new column in a grid. How to do this?
protected function _prepareCollection()
{
$collection = Mage::getModel('players/players')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns()
{
$this->addColumn('player_id', array(
'header' => Mage::helper('players')->__('ID'),
'align' =>'right',
'width' => '50px',
'index' => 'player_id',
));
$this->addColumn('name', array(
'header' => Mage::helper('players')->__('Name'),
'align' =>'left',
'index' => 'name',
));
return parent::_prepareColumns();
}
Well there are two ways to do it. The first, while easier is not preferred, is to "local include hack" it and move the grid from core/Mage/../.. to local/Mage../.. and simply make your changes are required.
The alternative is to do a rewrite of the file in a module config.xml:
<blocks>
<customadminhtml>
<class>Namespace_CustomAdminhtml_Block</class>
</customadminhtml>
<adminhtml>
<rewrite>
<sales_order_grid>Namespace_CustomAdminhtml_Block_Adminhtml_Sales_Order_Grid</sales_order_grid>
</rewrite>
</adminhtml>
</blocks>
In the rewritten file I would not both trying to override the "_prepareCollection" call. How are you going to call it and set the collection, logically, you can't insert your changes in there properly and still maintain original functionality. Instead I would override the "setCollection" method. By doing this you maintain the logic of the original _prepareCollection function and can insert your logic into the flow:
/**
* #brief Add customer_email to sales order
* #param Mage_Sales_Model_Resource_order_grid_collection $collection
*/
public function setCollection($collection)
{
/** #var Mage_Eav_Model_Config $eav */
$eav = Mage::getModel('eav/config');
$attribute = $eav->getAttribute('customer', 'customer_number');
$connection = $collection->getConnection();
$collection->join(array('sfo' => 'sales/order'), 'main_table.entity_id=sfo.entity_id', 'customer_email');
if ($attribute->getId()) {
$collection->getSelect()
->joinLeft(array('c' => $connection->getTableName('customer_entity_varchar')),
'main_table.customer_id = c.entity_id AND c.attribute_id = '.$attribute->getId(),
array('customer_number' => 'value'));
}
parent::setCollection($collection);
}
Finally, you can add the column by overriding the normal "_prepareColumns" function, just call the parent before hand:
public function _prepareColumns()
{
parent::_prepareColumns();
$this->addColumnAfter('customer_email', array(
'header' => Mage::helper('customer')->__('Customer Email'),
'width' => '50px',
'index' => 'customer_email',
), 'shipping_name');
$this->sortColumnsByOrder();
return $this;
}

Magento Backend Product list grid

Does anyone know how to add a field containing an input type text element or a dropdown element to a magento backend product list grid?
I managed to add a new column to my custom module backend product listing grid like this:
$this->addColumn('blabla', array(
'header' => Mage::helper('customer')->__('On Hold?'),
'width' => '120',
'index' => 'bla',
'type' => 'options',
'options' => array('1' => 'Yes', '0' => 'No')
));
but this command only adds the dropdown to my grid header, while i need the dropdown to appear in the left side of every product listed on that grid (just like the checkbox appears when you go for instance in backend on a product edit page and you select related products, or upsell products)
Simple and fast solution as tip for next research - rewrite Mage_Adminhtml_Block_Catalog_Product_Grid, function _prepareColumns. Example you will create your block Module_Name_Block_Sample:
class Module_Name_Block_Sample extends Mage_Adminhtml_Block_Catalog_Product_Grid
{
protected function _prepareColumns()
{
$this->addColumn('blabla', array(
'header' => Mage::helper('customer')->__('On Hold?'),
'width' => '120',
'index' => 'bla',
'type' => 'options',
'options' => array('1' => 'Yes', '0' => 'No')
));
return parent::_prepareColumns();
}
}
You will get it as first field. And it may need rewrite _prepareCollection.
But it may be not better solution, I know.
What you need is a custom renderer, where you can display any HTML you want. Something like this:
$this->addColumn('blabla', array(
'header' => Mage::helper('customer')->__('On Hold?'),
'width' => '120',
'index' => 'bla',
'renderer' => 'module/sample_grid_renderer'
));
And then you create your renderer class, where you create HTML you need:
class Module_Name_Block_Sample_Grid_Renderer
extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
public function render(Varien_Object $row)
{
$html = '<select name="row'.$row->getId().'"></select>';
return $html;
}
}
$country = $fieldset->addField('country', 'select', array(
'name' => 'country',
'label' => 'Country',
'values' => Mage::getModel('adminhtml/system_config_source_country') ->toOptionArray()
));
Try it! Have a nice day. Thank you.

Magento - grid pagination

I created grid in magento backend, but pagination doesn't work. No matter how many records per page I choose there are always all of them visible on the page. Now I have 41 records in database and 'stats' above the grid are ok (number of pages and records found):
Page 1 of 3 pages | View 20 per page | Total 41 records found
Which file is responsible of pagination?
There's also another problem with order by certain column. For ex. records are displayed the same way either I choose ASC or DESC order by ID...
Grid:
public function __construct() {
parent::__construct();
$this->setId('logger_grid');
$this->setUseAjax(FALSE);
$this->setDefaultSort('id');
$this->setDefaultDir(Varien_Data_Collection::SORT_ORDER_ASC);
$this->setSaveParametersInSession(TRUE);
}
public function _prepareCollection() {
$collection = Mage::getModel('logger/logger')->getCollection()->load();
$this->setCollection($collection);
return parent::_prepareCollection();
}
public function _prepareColumns() {
$this->addColumn('id', array(
'header' => Mage::helper('logger')->__('ID'),
'sortable' => TRUE,
'index' => 'log_id',
'editable' => FALSE,
));
$this->addColumn('interface', array(
'header' => Mage::helper('logger')->__('Interface'),
'sortable' => TRUE,
'index' => 'interface',
'editable' => FALSE,
));
$this->addColumn('type', array(
'header' => Mage::helper('logger')->__('Type'),
'sortable' => TRUE,
'index' => 'type',
'editable' => FALSE,
));
$this->addColumn('description', array(
'header' => Mage::helper('logger')->__('Description'),
'sortable' => TRUE,
'index' => 'description',
'editable' => FALSE,
));
$this->addColumn('message_data', array(
'header' => Mage::helper('logger')->__('Message'),
'sortable' => TRUE,
'index' => 'message_data',
'editable' => FALSE,
));
$this->addColumn('time', array(
'header' => Mage::helper('logger')->__('Time'),
'sortable' => TRUE,
'index' => 'time',
'editable' => FALSE,
'type' => 'datetime',
));
return parent::_prepareColumns();
}
public function getRowUrl($row) {
return $this->getUrl('*/*/edit', array('id' => $row->getId()));
}
Collection.php:
public function _construct(){
$this->_init("logger/logger");
}
Ok, problem solved. As always just one little thing...In _prepareCollection() function I used
$collection = Mage::getModel('logger/logger')->getCollection()->load(); and pagination didn't work because of load() function.
Thanks for replying, sparcksoft :)
If you created a custom collection resource model, it could be that you've overwritten or broken the implementation of {{_renderLimit()}} which, adds a limit to the underlying SQL query based on the current page and page size.
// Varien_Data_Collection_Db
protected function _renderLimit()
{
if($this->_pageSize){
$this->_select->limitPage($this->getCurPage(), $this->_pageSize);
}
return $this;
}
Can you post relevant portions from your collection resource model and maybe your grid block?
You can use this:
protected function _prepareCollection()
{
$collection = Mage::getModel('vendor/model')->getCollection();
$this->setCollection($collection);
//
return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
}
In this case you can reach your custom model and display with pagination
To fix this, you need to edit one of your core file please follow the below link:
https://raisereview.com/wrong-grid-count-and-pagination-issue-in-magento-admin-grid/

Adding data from customer_entity_varchar to order grid magento

I am trying to add 'accountno' field to order grid from customer_entity_varchar table. To achieve this I changed _prepareCollection() method in Grid.php like this:
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
$customerEntityVarchar = Mage::getSingleton('core/resource')->getTableName('customer_entity_varchar');
$collection->getSelect()->join(array(
'customer_entity_varchar_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
AND `customer_entity_varchar_table`.`attribute_id`=122',
array('accountno' => 'value'));
print_r($collection->getSelect()->__toString());
$this->setCollection($collection);
return parent::_prepareCollection();
}
In attribute_id=122' 122 is the attribute_id ofaccountno`
When I print_r the select query and execute it in phpmyadmin, it gets me the accurate results back but when I try to add Column to grid in _prepareColumns() method, it shows the field blank.
My _prepareColumns method looks like this:
protected function _prepareColumns()
{
$this->addColumn('real_order_id', array(
'header'=> Mage::helper('sales')->__('Order #'),
'width' => '80px',
'type' => 'text',
'index' => 'increment_id',
));
$this->addColumnAfter('accountno', array(
'header' => Mage::helper('sales')->__('Account No'),
'index' => 'accountno',
), 'real_order_id');
//rest of the code here
}

magento adminhtml custom module it's showing the grid twice

i am new to magento by following this guide Custom Module with Custom Database Table
i have implemented my already existed module to the backend adminhtml. i am taking stuff from the database and sjowing ot on the adminhtml page. Everything works ok except i am getting the grid twice on the adminhtml. i am getting the same Grid two time. i have looked the code for like 2 hours cannot figure it out. if anyone one knows how to fix this problem i will be greatly thakful. cheers
thats the code from my grid.php
<?php
class Ecom_Pricenotify_Block_Adminhtml_Pricenotify_Grid extends Mage_Adminhtml_Block_Widget_Grid{
public function __construct()
{
parent::__construct();
$this->setId('pricenotifyGrid');
// This is the primary key of the database
$this->setDefaultSort('pricenotify_id');
$this->setDefaultDir('ASC');
$this->setSaveParametersInSession(true);
}
protected function _prepareCollection()
{
$collection = Mage::getModel('pricenotify/pricenotify')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns()
{
$this->addColumn('pricenotify_id', array(
'header' => Mage::helper('pricenotify')->__('Notification ID'),
'align' =>'left',
'width' => '50px',
'index' => 'pricenotify_id',
));
$this->addColumn('prod_id', array(
'header' => Mage::helper('pricenotify')->__('Product ID'),
'align' =>'left',
'width' => '50px',
'index' => 'prod_id',
));
$this->addColumn('prod_price', array(
'header' => Mage::helper('pricenotify')->__('Product Price'),
'align' =>'left',
'width' => '50px',
'index' => 'prod_price',
));
$this->addColumn('user_price', array(
'header' => Mage::helper('pricenotify')->__('User Price'),
'align' =>'left',
'width' => '50px',
'index' => 'user_price',
));
$this->addColumn('email', array(
'header' => Mage::helper('pricenotify')->__('E-Mail Address'),
'align' =>'left',
'width' => '150px',
'index' => 'email',
));
$this->addColumn('created_time', array(
'header' => Mage::helper('pricenotify')->__('Creation Time'),
'align' => 'left',
'width' => '120px',
'type' => 'date',
'default' => '--',
'index' => 'created_time',
));
$this->addColumn('status', array(
'header' => Mage::helper('pricenotify')->__('Status'),
'align' => 'left',
'width' => '80px',
'index' => 'status',
'type' => 'options',
'options' => array(
'success' => 'Inactive',
'pending' => 'Active',
),
));
return parent::_prepareColumns();
}
public function getRowUrl($row)
{
return $this->getUrl('*/*/edit', array('id' => $row->getId()));
}}
and this indexAction function is from the controller
public function indexAction() {
$this->_initAction();
$this->_addContent($this->getLayout()->createBlock('pricenotify/adminhtml_pricenotify'));
$this->renderLayout();
}
Maybe you're inserting it in the layout, check pricenotify.xml in
adminhtml>default>default>layout.
Such as:
<pricenotify_adminhtml_manager_pricenotify>
<block type="core/text_list" name="root" output="toHtml">
<block type="pricenotify/adminhtml_pricenotify_grid" name="pricenotify.grid"/>
</block>
</pricenotify_adminhtml_manager_pricenotify>
Remove this block or comment the line where you add the content.
I fixed it. i only had to comment out
//$this->_addContent($this->getLayout()->createBlock('pricenotify/adminhtml_pricenotify'));
from indexAction i guess iwas loading it twice.
make sure that the grid block isn't already loaded in the corresponding layout.xml file.
Well I was facing the same issue but in my case it was due to $this->setId('messages'); line (in your Grid.php construct). Because magento already has same <div id="messages"></div> in its grid page(for showing notifications) due to which my grid content was getting loaded within this 'div' tag hence showing grid twice. So lesson learned is don't give general name while setting your 'id' in Grid.php which could already be present in the grid page.
In my case, it's happened on Edit/Form, and I had duplicated unintentionally renderLayout() on my Adminhtml controller.
$this->renderLayout();

Resources