Magento Admin Custom Grid

Creating a Magento admin custom grid might seem like a difficult task at first. This tutorial will hopefully make things a lot easier for you, and aid you in understanding how Magento grids work.

For this article we will assume that you have set up an area in the Magento admin that you can use to display your grid, as well as setting up some data that you can use to display in the grid. Remember the Store Info example we used for the Models, Resource Models and Collections guide? We’ll be using this data for purpose for this article.

To give an overview of the components needed for a Magento custom grid, Magento uses a Grid Container class, Mage_Adminhtml_Block_Widget_Grid_Container, as well as a Grid class, Mage_Adminhtml_Block_Widget_Grid.

Firstly, we need to add a block to our adminhtml layout XML file. This block will extend the Magento grid container class. So if you haven’t done so, we need to first declare our layout file in the module’s config.xml file.

<?xml version="1.0"?>
<config>
    ....
    <adminhtml>
        <layout>
            <updates>
                <storeinfo>
                    <file>storeinfo.xml</file>
                </storeinfo>
            </updates>
        </layout>
    </adminhtml>
</config>

Then in our storeinfo.xml file, we need to add our container block. Note that the layout handle (adminhtml_managestores_index) used below may differ from yours, depending how how you’ve set up your adminhtml router to display the page in the admin.

<?xml version="1.0"?>
<layout>
    <adminhtml_managestores_index>
        <reference name="content">
            <block type="storeinfo/adminhtml_stores" name="stores" />
        </reference>
    </adminhtml_managestores_index>
</layout>

So as per the second half of the block type, we’re specifying that our block file is located at /Block/Adminhtml/Store.php

If you haven’t already done so, ensure that you have declared that you are using blocks in your config.xml file.

<?xml version="1.0"?>
<config>
    <global>
        <blocks>
            <storeinfo>
                <class>Custom_Storeinfo_Block</class>
            </storeinfo>
        </blocks>
    </global>
</config>

To reiterate about the use of the type attribute used in storeinfo.xml, the first part before the “/” takes the name from the alias under the blocks node in config.xml, so for this example, it is storeinfo and hence we get a block type of storeinfo/adminhtml_stores.

Now we move on to creating our block container class.

<?php
class Custom_Storeinfo_Block_Adminhtml_Stores extends Mage_Adminhtml_Block_Widget_Grid_Container {
    
}

We then need to add our __construct() method.

<?php
class Custom_Storeinfo_Block_Adminhtml_Stores extends Mage_Adminhtml_Block_Widget_Grid_Container {
    public function __construct() {
        $this->_controller = 'adminhtml_stores'; // path to the grid container file
        $this->_blockGroup = 'storeinfo'; // config.xml block alias
        $this->_headerText = Mage::helper('storeinfo')->__('Store Manager');
        $this->_addButtonLabel = Mage::helper('storeinfo')->__('Add Store');
        parent::__construct();
    }
}

So, we’ve successfully extended the Mage_Adminhtml_Block_Widget_Grid_Container class. Let’s go through some of the properties that have been set.

  • $this->_controller – Not to be confused with controllers involved in routing. This is more of a ‘container controller’ that specifies the container block. The value will need to be the same as we used the second half of our “block type” value in our storeinfo.xml layout file.
  • $this->_blockGroup – This is simply the block alias used in config.xml.
  • $this->_headerText – The header text, usually in orange, that appears just above the grid when viewing the page in the admin
  • $this->_addButtonLabel – The label for the “Add __” orange button that appears on the top right hand side just above the grid. For our example, it will be Add Store.

Notice that the last two use a helper file? If you haven’t already set one up, you’ll ned to do so.

<?xml version="1.0"?>
<config>
    <global>
        <helpers>
            <storeinfo>
                <class>Custom_Storeinfo_Helper</class>
            </storeinfo>
        </helpers>
    </global>
</config>
<?php
class Custom_Storeinfo_Helper_Data extends Mage_Core_Helper_Abstract {

}

Now we move on to the grid itself. Magento’s naming conventions suggest that our grid file should be called Grid.php, and it should be located within a directory that has the same name as our grid container file.

Our grid container file was called Stores so the directory should be app/code/local/Custom/Storeinfo/Block/Adminhtml/Stores/Grid.php.

Remember, this file should extend the Mage_Adminhtml_Block_Widget_Grid class.

<?php
class Custom_Storeinfo_Block_Adminhtml_Stores_Grid extends Mage_Adminhtml_Block_Widget_Grid {
}

Of course, we need to add a few things to this class to actually display our data.

1. Similar to our grid container file, our Grid.php should also contain a __construct() method so we can set some default values.

public function __construct()
{
    parent::__construct();

    // Set some defaults for our grid
    $this->setDefaultSort('id');
    $this->setId('manage_stores_grid');
    $this->setDefaultDir('asc');
    $this->setSaveParametersInSession(true);
}

2. We need to prepare our collection, using the _prepareCollection() method.

protected function _prepareCollection()
{
    // Get and set our collection for the grid
    $collection = Mage::getModel('storeinfo/store')->getCollection();
    $this->setCollection($collection);

    return parent::_prepareCollection();
}

3. We then should prepare our columns, using the _prepareColumns() method.

protected function _prepareColumns()
{
    // Add the columns that should appear in the grid
    $this->addColumn('store_id',
        array(
            'header'=> $this->__('Store ID'),
            'align' =>'right',
            'width' => '50px',
            'index' => 'store_id'
        )
    );

    $this->addColumn('name',
        array(
            'header'=> $this->__('Name'),
            'index' => 'name'
        )
    );

    $this->addColumn('description',
        array(
            'header'=> $this->__('Description'),
            'index' => 'description'
        )
    );

    return parent::_prepareColumns();
}

The first parameter of the addColumn() method is used for the name attribute of the anchor element that sits within the table header (th) element.

The header key will be the label of the column name that displays on the grid.

The index key must match the column name you specified when creating the database table.

4. And finally, our rows of data should be clickable so that we can edit their values if we need to. Therefore we need to add a getRowUrl() method.

public function getRowUrl($row)
{
    // This is where our row data will link to
    return $this->getUrl('*/*/edit', array('id' => $row->getId()));
}

Of course, the row links will not go anywhere at the moment, nor will the Add button above the grid. This is because we haven’t configured any of the forms yet.

To learn how you can add forms within the admin area of Magento, check out this article.

Note: This article is based on Magento Community/Open Source version 1.9.