Ultimate Magento Admin Interface Customization Guide

Would you like to know how it is possible to set up a separate admin menu and add a grid/form to it? And what if you could organize your customers into a separately administered category structure so that you could offer custom deals to each of the customer categories? These needs can all be addressed within the Magento ecommerce framework by adding customized admin menus, grids and forms.

In this article we will describe:

  • How to create a new Magento admin menu
  • How to add a grid to the menu
  • How to create forms and inputs within them
  • How tabs work in the forms

 

There are two approaches to this challenge:

  1. A new admin menu should be set up for category listing and editing, and then adding a new tab to the customer editing where we can assign the relevant categories to the given customer.
  2. We add a customer list to the category editing where we can assign the customers to the given category. In the final solution we describe this second option because here we can handle these settings in one single location.

Planned steps of implementation:

  1. Planning of database items (database modifications are not described in this article)
  2. Creating new modules a (Customercategory)
    • Könyvtár struktúra létrehozása
    • magento customer category directory structure
    • Creating the necessary model, resource model, helper installers
    • App/etc/modules/Aion_Customercategory.xml
    • Creating the config.xml in the module’s etc library
    • Creating controllers
    • Creating Blocks
    • Creating Layout
    • Creating language files (csv)

Creating the module

Within Magento, when creating a new module, first we need to create a library (Customercategory) – where we want to place the module –, in the selected pool (local in our case), under namespace (aion). At the same time we create [module name].xml under app/etc/modules.


<?xml version="1.0"?>
 <config>
     <modules>
         <!-- namespace_modulename -->
         <Aion_Customercategory>
             <active>true</active>
             <!-- pool -->
             <codePool>local</codePool>
         </Aion_Customercategory>
     </modules>
 </config>

Library structure of the module:

  • Block – forms, grids and similar classes to be shown will be placed here
  • controllers – this contains controllers
  • etc – location of xml files to be used (config.xml, adminhtml.xml, …)
  • Helper – location of helper files
  • Model – location of model files
  • sql – location of database installer/update files

We need to set the basic actions in the config.xml of the module’s etc library to make our module functional:


<?xml version="1.0"?>
 <config>
     <modules>
         <Aion_Customercategory>
             <version>0.1.0</version>
         </Aion_Customercategory>
     </modules>
     <global>
         <models>
             <aion_customercategory>
                 <class>Aion_Customercategory_Model</class>
                 <resourceModel>aion_customercategory_resource</resourceModel>
             </aion_customercategory>
             <aion_customercategory_resource>
                 <class>Aion_Customercategory_Model_Resource</class>
                 <entities>
                     <category>
                         <table>aion_customercategory_category</table>
                     </category>
                     <customer>
                         <table>aion_customercategory_customer</table>
                     </customer>
                 </entities>
             </aion_customercategory_resource>
         </models>
         <blocks>
             <aion_customercategory>
                 <class>Aion_Customercategory_Block</class>
             </aion_customercategory>
         </blocks>
         <helpers>
             <aion_customercategory>
                 <class>Aion_Customercategory_Helper</class>
             </aion_customercategory>
         </helpers>
         <resources>
             <aion_customercategory_setup>
                 <setup>
                     <class>Mage_Core_Model_Resource_Setup</class>
                     <module>Aion_Customercategory</module>
                 </setup>
             </aion_customercategory_setup>
         </resources>
     </global>
 </config>

After finishing with the basic tasks, we need to create a menu in the admin panel to handle the different items. In our case we create this in the Customer main menu so we insert the following into the config.xml:

 </global>

     <adminhtml>
         <menu>
             <customer>
                 <children>
                     <aion_customercategory>
                         <title>Customer Categories</title>
                         <sort_order>9999</sort_order>
                         <action>adminhtml/customercategory/index</action>
                     </aion_customercategory>
                 </children>
             </customer>
         </menu>
     </adminhtml>
 </config>

We can see that we need to set the XML structure in a way that we want to define a menu (<menu>) in the admin (<adminhtml>), where we create a sub menu (<children>) under Customers (<customer>) and where we give the following settings: :

  • title – title of the menu
  • sort order – in which line should the menu be located
  • action – which method of which controller should be run when clicking on the menu

Now if we take a look at the admin panel, we can see the following (it is very important to empty the Magento cache after every modification in xml, so that fresh data are reloaded):

Magento Admin Grid Customization

Now we need to script the controller to address the call: We need to create a class/method pair in the xml as an action under the controllers library (every ending of every controller is Controller and all the methods need to have endings of Action). Since it will be an admin controller, it should be derived from the Mage_Adminhtml_Controller_Action parent class. controllers/Adminhtml/CustomercategoryController.php

class Aion_Customercategory_Adminhtml_CustomercategoryController
    extends Mage_Adminhtml_Controller_Action
 {
     public function indexAction()
     {
         die('ok');
     }
 }


Next we need to “tell” Magento to use our controllers by inserting the following data in the config.xml:

</adminhtml>
<admin>  
    <routers> 
        <adminhtml> 
            <args>  
                <modules> 
                    <Aion_Customercategory before="Mage_Adminhtml">Aion_Customercategory_Adminhtml</Aion_Customercategory>  
                </modules>     
            </args>    
        </adminhtml> 
    </routers>
</admin>

So it should handle the paths we defined before handling the Magento router. The after item is also an option (in our case it is irrelevant). However, if we want to use a system url, then before is the suitable property, so that our controller/action pair is run before default (after the changes were made, we need to empty the cache so that Magento can read the modifications). Now our method can be run, but we need to define the layout in order to set what form it should take after rendering. This should also be given in xml format including the following steps.

  • We need to define in the config.xml, under the adminhtml tag, those layout.xml files that we want to use:

...
</menu>
     <layout>
         <updates>
             <aion_customercategory>
                 <file>aion/customercategory.xml</file>
             </aion_customercategory>
         </updates>
     </layout>
 </adminhtml>
...

  • We need to load the layout in the indexAction and then render it out

class Aion_Customercategory_Adminhtml_CustomercategoryController
    extends Mage_Adminhtml_Controller_Action
 {
     public function indexAction()
     {
         $this->loadLayout();
         $this->renderLayout();
     }
 }

  • We need to create these under app/design/adminhtml/default/default/layout (which means that the describing file of our module’s layout xml will be /app/design/adminhtml/default/default/layout/aion/customercategory.xml).
    
    

<?xml version="1.0"?>
 <layout version="0.1.0">
     <adminhtml_customercategory_index>
         <reference name="menu">
             <action method="setActive">
                 <menupath>customer/customercategory</menupath>
             </action>
         </reference>
         <reference name="content">
             <block
                type="aion_customercategory/adminhtml_category"
                name="category_index"
            />
         </reference>
     </adminhtml_customercategory_index>
 </layout>

In the above example we define the layout of the adminhtml/customercategory/index (<adminhtml_customercategory_index>)path where we set that the selected menu customer/customercategory and its content will be an adminhtml/category block created by us.

Creating an index block

Naturally, when a user clicks on our menu, he or she would like to see a list with the items he or she selected, as well as would like to edit / create / delete items. In the above layout we set that our block will be the adminhtml_category, thus we need to create the app/code/local/Aion/Customercategory/Block/Adminhtml/Category.php, which manages the content given in the layout:

class Aion_Customercategory_Block_Adminhtml_Category

extends Mage_Adminhtml_Block_Widget_Grid_Container
{

public function __construct()
{
$this->_blockGroup = 'aion_customercategory';
$this->_controller = 'adminhtml_category';

parent::__construct();

$this->_headerText = $this->__('Customer Categories');
$this->_addButtonLabel = $this->__('Add New');

}
}

We can see that our class is derived from Mage_Adminhtml_Block_Widget_Grid_Container because here we want to display a grid later on. Within the constructor we need to set the _blockGroup and the _controller by which we tell Magento to create our grid block from Aion_Customercategory_Block_Adminhtml_Category_Grid. When the parent class renders out the layout, the following function is run:  

$this
->getLayout()
->createBlock(
$this->_blockGroup.'/' . $this->_controller . '_grid',
$this->_controller . '.grid'
)

Grid block

We need to create the grid class set above under app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Grid.php:

class Aion_Customercategory_Block_Adminhtml_Category_Grid
extends Mage_Adminhtml_Block_Widget_Grid
 {
public function __construct()
 {
 parent::__construct();
 }
protected function _prepareCollection()
 {
 return parent::_prepareCollection();
 }
protected function _prepareColumns()
 {
 return parent::_prepareColumns();
 }
 }

Our class derives from Mage_Adminhtml_Block_Widget_Grid, however we need to overwrite 3 methods so that it can function in our own module:

  • __construct – We need to set certain basic settings when creating instance
  • _prepareCollection – Defines where to call collection from
  • _prepareColumns – Defines what type of columns should be in the grid

The class, comprising our solutions, looks like this:

class Aion_Customercategory_Block_Adminhtml_Category_Grid extends Mage_Adminhtml_Block_Widget_Grid
 {
public function __construct()
 {
 parent::__construct();
 $this->setId('category_id');
 $this->setDefaultSort('category_id');
 $this->setDefaultDir('asc');
 $this->setSaveParametersInSession(true);
 }
protected function _prepareCollection()
 {
 $collection = Mage::getModel('aion_customercategory/category')
->getCollection();
 $this->setCollection($collection);
 return parent::_prepareCollection();
 }
protected function _prepareColumns()
 {
 $this->addColumn(
 'category_id',
 array(
 'header' => $this->__('ID'),
 'align'  => 'right',
 'width'  => '50px',
 'type'   => 'number',
 'index'  => 'category_id',
 )
 );
$this->addColumn(
 'name',
 array(
 'header' => $this->__('Name'),
 'index'  => 'name',
 )
 );
$this->addColumn(
 'active',
 array(
 'header'   => $this->__('Active'),
 'index'    => 'active',
 'type'     => 'options',
 'options'  => array(
 1 => Mage::helper('adminhtml')->__('Yes'),
 0 => Mage::helper('adminhtml')->__('No')
 ),
 )
 );
return parent::_prepareColumns();
 }
 }

After implementing this code, the following appears:

Magento Admin Grid Modification

We can see that we have a grid which needs to be completed.

Creating a form

Along with fulfilling the planning/implementing criteria, it is recommended to manage the “creating new” and “edit existing” forms with a common class. Thus the following modifications should be made in the controller:

class Aion_Customercategory_Adminhtml_CustomercategoryController
extends Mage_Adminhtml_Controller_Action
 {
...
 public function editAction()
 {
 $id    = $this->getRequest()->getParam('id');
 $model = Mage::getModel('aion_customercategory/category');
if ($id) {
 $model->load($id);
 if (!$model->getId()) {
 $this->_getSession()->addError(
 $this->__('This Category no longer exists.')
 );
 $this->_redirect('*/*/');
 return;
 }
 }
$data = $this->_getSession()->getFormData(true);
 if (!empty($data)) {
 $model->setData($data);
 }
Mage::register('current_model', $model);
$this
 ->loadLayout()
 ->renderLayout();
 }
 public function newAction()
 {
 $this->_forward('edit');
 }
...
 }

So, when creating new, it should redirect to Edit and is validated there. If there is an ID parameter, it loads the necessary data. Just like it was needed in case of the indexAction, here too it should be defined in the layout xml how the page is built up:

<?xml version="1.0"?>
 <layout version="0.1.0">
...
<adminhtml_customercategory_edit>
 <update handle="editor"/>
 <reference name="menu">
 <action method="setActive">
 <menupath>customer/customercategory</menupath>
 </action>
 </reference>
 <reference name="content">
 <block
type="aion_customercategory/adminhtml_category_edit"
name="category_edit"
/>
 </reference>
 <reference name="left">
 <block
type="aion_customercategory/adminhtml_category_edit_tabs"
name="category_tabs"
/>
 </reference>
 </adminhtml_customercategory_edit>
...
 </layout>

In the edit panel the content will be the category editor (reference name=”content”), on the left hand side it will be the tabs (reference name=”left”). In order to make something appear on the page, these two blocks should be created. The first block is adminhtml_category_edit, which we need to define under app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Edit.php:

class Aion_Customercategory_Block_Adminhtml_Category_Edit
extends Mage_Adminhtml_Block_Widget_Form_Container
 {
 protected function _getHelper()
 {
 return Mage::helper('aion_customercategory');
 }
public function __construct()
 {
 parent::__construct();
 $this->_blockGroup = 'aion_customercategory';
 $this->_controller = 'adminhtml_category';
 $this->_mode       = 'edit';
 $this->_updateButton(
'save',
'label',
$this->_getHelper()->__('Save Category')
);
 $this->_addButton(
'saveandcontinue',
array(
 'label'   => $this->_getHelper()->__(
'Save and Continue Edit'
),
 'onclick' => 'saveAndContinueEdit()',
 'class'   => 'save',
 ), -100);
$this->_formScripts[] = "
 function saveAndContinueEdit(){
 editForm.submit($('edit_form').action+'back/edit/');
 }
 ";
 }
 }

This is a Mage_Adminhtml_Block_Widget_Form_Container, and the form itself, based on the _blockGroup, _controller, _mode, is loaded from the class Aion_Customercategory_Adminhtml_Category_Edit_Form. We create this class in the app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Edit/Form.php file:

class Aion_Customercategory_Block_Adminhtml_Category_Edit_Form
extends Mage_Adminhtml_Block_Widget_Form
 {
 protected function _prepareForm()
 {
 $form = new Varien_Data_Form(array(
 'id'      => 'edit_form',
 'method'  => 'post',
 'enctype' => 'multipart/form-data',
 'action'  => $this->getUrl('*/*/save'),
 )
 );
 $form->setUseContainer(true);
 $this->setForm($form);
 return parent::_prepareForm();
 }
 }

We have an empty form, now we need to create the class managing the tabs. We set the adminhtml_category_edit_tabs for the block in the layout.xml, therefore the name of the class should be Aion_Customercategory_Block_Adminhtml_Category_Edit_Tabs. Thus the file should be app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Edit/Tabs.php:

class Aion_Customercategory_Block_Adminhtml_Category_Edit_Tabs
extends Mage_Adminhtml_Block_Widget_Tabs
 {
 public function __construct()
 {
 parent::__construct();
 $this->setId('category_tabs');
 $this->setDestElementId('edit_form');
 $this->setTitle(
Mage::helper('aion_customercategory')->__('Details')
);
 }
protected function _beforeToHtml()
 {
 $this->addTab(
 'category_section',
 array(
 'label' => Mage::helper('aion_customercategory')
->__('Category'),
 'title' => Mage::helper('aion_customercategory')
->__('Category'),
 'content' => $this->getLayout()
->createBlock(
'aion_customercategory/adminhtml_category_edit_category_form'
)->toHtml(),
 )
 );
 return parent::_beforeToHtml();
 }
 }

We can see that it can be set with the __consturctor what the identification will be, into which forms items will be loaded or what titles are seen above the tabs. We set the tabs dynamically in the _beforeToHtml, so the number of addTab() present here will be the number on the list as well. Now we need to create the adminhtml_category_edit_category_form block, which denotes the Aion_Customercategory_Block_Adminhtml_Category_Edit_Category_Form class, which will be in the app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Edit/Category/Form.php file:

class Aion_Customercategory_Block_Adminhtml_Category_Edit_Category_Form
extends Mage_Adminhtml_Block_Widget_Form
 {
 protected function _getModel()
 {
 return Mage::registry('current_model');
 }
protected function _getHelper()
 {
 return Mage::helper('aion_customercategory');
 }
protected function _prepareForm()
 {
 $model = $this->_getModel();
 $form  = new Varien_Data_Form(array(
 'id'     => 'edit_form',
 'action' => $this->getUrl('*/*/save'),
 'method' => 'post'
 ));
$fieldset = $form->addFieldset('base_fieldset', array(
 'legend' => $this->_getHelper()->__('Category Information'),
 'class'  => 'fieldset-wide',
 ));
if ($model && $model->getId()) {
 $modelPk = $model->getResource()->getIdFieldName();
 $fieldset->addField($modelPk, 'hidden', array(
 'name' => $modelPk,
 ));
 }
$fieldset->addField('name', 'text', array(
 'name'     => 'name', 'required' => true,
 'label'    => $this->_getHelper()->__('Name'),
 'title'    => $this->_getHelper()->__('Name'),
 )
 );
$fieldset->addField('active', 'select', array(
 'name'     => 'active', 'required' => true,
 'label'    => $this->_getHelper()->__('Active'),
 'title'    => $this->_getHelper()->__('Active'),
 'options'  => array(
 '1' => Mage::helper('adminhtml')->__('Yes'),
 '0' => Mage::helper('adminhtml')->__('No'),
 ),
 )
 );
if ($model) {
 $form->setValues($model->getData());
 }
 $this->setForm($form);
return parent::_prepareForm();
 }
 }

Besides the auxiliary methods we add the necessary fields to the panel in the _prepareForm() function. We then see a panel if we take a look at the page:

Magento Custom Admin Form Development

Thanks to this, we have created the panel of “creating new” and “edit item”, but we also need to save the data entered in the form. For this we need to define a saveAction() method in the controller (CustomercategoryController):

...
public function saveAction()
 {
 $redirectBack = $this->getRequest()->getParam('back', false);
 if ($data = $this->getRequest()->getPost()) {
 $id    = $this->getRequest()->getParam('id');
 $model = Mage::getModel('aion_customercategory/category');
 if ($id) {
 $model->load($id);
 if (!$model->getId()) {
 $this->_getSession()->addError(
 $this->__('This Category no longer exists.')
 );
 $this->_redirect('*/*/index');
 return;
 }
 }
try {
 $model->addData($data);
 $this->_getSession()->setFormData($data);
 $model->save();
 $this->_getSession()->setFormData(false);
 $this->_getSession()->addSuccess(
 $this->__('The Category has been saved.')
 );
 } catch (Mage_Core_Exception $e) {
 $this->_getSession()->addError($e->getMessage());
 $redirectBack = true;
 } catch (Exception $e) {
 $this->_getSession()->addError(
$this->__('Unable to save the Category.')
);
 $redirectBack = true;
 Mage::logException($e);
 }
if ($redirectBack) {
 $this->_redirect('*/*/edit', array('id' => $model->getId()));
 return;
 }
 }
 $this->_redirect('*/*/index');
 }
...

After saving, we find the items in the list that we entered:

Magento custom admin form save data

The general grid functions are already operational because of the class derived from Magento:

  • filtering
  • ordering
  • paging

We need to set what url should be activated if we click on a certain line. We do this in the Aion_Customercategory_Block_Adminhtml_Category_Grid class with the help of the following method:

public function getRowUrl($row)
 {
 return $this->getUrl('*/*/edit', array('id' => $row->getId()));
 }

In order to accomplish full functionality, deleting is also necessary, which can be reached from the editing form. After a confirmation pop-up it automatically redirects to the deleteAction() function. Therefore we need to implement that as well in the controller:

public function deleteAction()
 {
 if ($id = $this->getRequest()->getParam('id')) {
 try {
 $model = Mage::getModel('aion_customercategory/category');
 $model->load($id);
 if (!$model->getId()) {
 Mage::throwException($this->__('Unable to find a Category to delete.'));
 }
 $model->delete();
 $this->_getSession()->addSuccess(
 $this->__('The Category has been deleted.')
 );
 $this->_redirect('*/*/index');
 return;
 } catch (Mage_Core_Exception $e) {
 $this->_getSession()->addError($e->getMessage());
 } catch (Exception $e) {
 $this->_getSession()->addError(
 $this->__('An error occurred while deleting Category data. Please review log and try again.')
 );
 Mage::logException($e);
 }
 $this->_redirect('*/*/edit', array('id' => $id));
 return;
 }
 $this->_getSession()->addError(
 $this->__('Unable to find a Category to delete.')
 );
 $this->_redirect('*/*/index');
 }

Thanks to this, we can edit the categories. If we want to change the structure, we simply need to remove or add fields in the form by deleting or using the addField() method respectively. In order to be able to add customers to the categories in the planning phase, the ajax tab solution is recommended. A new tab should be added in the Aion_Customercategory_Block_Adminhtml_Category_Edit_Tabs class, which loads in the customer grid in an “ajax-based” way.  

protected function _beforeToHtml()
 {
 ...
 $this->addTab('customers', array(
 'label'     => $this->__('Customers'),
 'title'     => $this->__('Customers'),
 'url'       => $this->getUrl(
'*/*/customerstab',
array('_current' => true)
),
 'class'     => 'ajax'
 ));
return parent::_beforeToHtml();
 }

It can be seen under the url key that our controller’s customerstabAction method is called, in which we set the necessary data:

public function customerstabAction()
 {
 $saved_customer_ids = array();
 //Your load logic
 $this
 ->loadLayout()
 ->getLayout()
 ->getBlock('category.customer.tab')
 ->setSelectedCustomers($saved_customer_ids);
$this->renderLayout();
 }

It is important, however, that, as with all admin items, this too needs a descriptive block about what it should include:

...
<adminhtml_customercategory_customerstab>
 <block type="core/text_list" name="root" output="toHtml">
 <block type="aion_customercategory/adminhtml_category_edit_customer_grid" name="category.customer.tab"/>
</block>
 </adminhtml_customercategory_customerstab>
...

We need to create the block necessary, which is the following in our example: adminhtml_category_edit_customer_grid -> Aion_Customercategory_Block_Adminhtml_Category_Edit_Customer_Grid -> app/code/local/Aion/Customercategory/Block/Adminhtml/Category/Edit/Customer/Grid.php As he have already executed this with our previous grid, the __construct(), _prepareCollection(), _prepareColumns() methods should be set here as well:

class Aion_Customercategory_Block_Adminhtml_Category_Edit_Customer_Grid extends Mage_Adminhtml_Block_Widget_Grid
 {
 public function __construct()
 {
 parent::__construct();
 $this->setId('customerGrid');
 $this->setUseAjax(true);
 $this->setSaveParametersInSession(true);
 }
protected function _prepareCollection()
 {
 $collection = Mage::getResourceModel('customer/customer_collection')
 ->addNameToSelect();
$this->setCollection($collection);
 return parent::_prepareCollection();
 }
protected function _prepareColumns()
 {
 $this->addColumn('selected_customers', array(
 'header'    => $this->__('Select'),
 'type'      => 'checkbox',
 'index'     => 'entity_id',
 'align'     => 'center',
 'field_name'=> 'selected_customers[]',
 'values'    => $this->getSelectedCustomers(),
 ));
$this->addColumn('customer_name', array(
 'header'    => $this->__('Name'),
 'index'     => 'name',
 'align'     => 'left',
 ));
$this->addColumn('email', array(
 'header'    => $this->__('E-mail'),
 'index'     => 'email',
 'align'     => 'left',
 ));
return parent::_prepareColumns();
 }
 }

If the constructor contains setUseAjax(true), then it will read the grid in an “ajax-based” way, however, the gridUrl should also be given in this class:

public function getGridUrl()
 {
 return $this->getUrl('*/*/customersgrid', array('_current' => true));
 }

This, logically, is a controller/action call, therefore this should be managed in the controller as well:

public function customersgridAction()
 {
 $this
 ->loadLayout()
 ->getLayout()
 ->getBlock('category.customer.tab')
 ->setSelectedCustomers(
$this->getRequest()->getPost('customers', null)
);
$this->renderLayout();
 }

In order to render out this “ajax-based” page without any errors, we need to give the following data in the layout.xml:

...
<adminhtml_customercategory_customersgrid>
<block type="core/text_list" name="root" output="toHtml">
<block type="aion_customercategory/adminhtml_category_edit_customer_grid" name="category.customer.tab"/>
</block>
</adminhtml_customercategory_customersgrid>
...

When we have finished with this, we can see our “ajax-based” customer grid under a tab:

Magento Admin Customer Grid

The next step is to store the selected customer entities in the given category, which means we need to put the IDs in a hidden input, so that these would be stored after saving. This is necessary because if we checked only the checkboxes selected in the grid, then after paging or filtering, the selected checkbox may not appear anymore and thus we could not include it as a part of the saving process. Thankfully, Magento provides a solution to this problem. We need to complement our tab with a new block (widget_grid_serializer), which manages this, so we only have to make some major settings and modifications in our code:

...
<adminhtml_customercategory_customerstab>
<block type="core/text_list" name="root" output="toHtml">
<block type="aion_customercategory/adminhtml_category_edit_customer_grid" name="category.customer.tab"/>
<block type="adminhtml/widget_grid_serializer" name="category.customer.serializer">
<action method="initSerializerBlock">
<grid_block_name>category.customer.tab</grid_block_name>
<data_callback>getSelectedCustomerIds</data_callback>
<hidden_input_name>customer_ids</hidden_input_name>
<reload_param_name>customers</reload_param_name>
</action>
</block>
    </block>
</adminhtml_customercategory_customerstab>
...

It can be seen that it calls the initSerializerBlock() method, which has the following parameters:

  • grid_block_name – defines wich grid the serialization applies to
  • data_callback – defines which created method returns the already selected IDs
  • hidden_input_name – defines the name of the input (we will refer with this name to the specific html tag later in the post)
  • reload_param_name – defines the parameter that contains the already stored items

Now we need to create the getSelectedCustomerIds() function in the Aion_Customercategory_Block_Adminhtml_Category_Edit_Customer_Grid class, which returns the identifiers set in the category:

public function getSelectedCustomerIds()
 {
 $returnArray = array();
 //Your getter logic
 return $returnArray;
 }

With this, loading has been effectuated, now the saving process should be completed with the storing of the selected identifiers. It is important that the data in the input are serialized so we need to decrypt to be able to store them. It should be carried out within CustomercategoryController saveAction():

public function saveAction()
 {
 $redirectBack = $this->getRequest()->getParam('back', false);
 if ($data = $this->getRequest()->getPost()) {
 ...
if ($customersIds = $this->getRequest()->getParam('customer_ids', null)) {
 $customersIds = Mage::helper('adminhtml/js')
->decodeGridSerializedInput($customersIds);
 //Your save logic
 }
if ($redirectBack) {
 $this->_redirect('*/*/edit', array('id' => $model->getId()));
 return;
 }
 }
 ...
}

Finally, there is one more thing needed to have a fully functional panel. This is the function with wich the user can filter the customers in the list that are already selected as well as those that are not.

Magento Admin Customer Grid Filter

This can be solved by adding a method to the Aion_Customercategory_Block_Adminhtml_Category_Edit_Customer_Grid , which we can set when adding a column, indicating what the filter function should be:

$this->addColumn('selected_customers', array(
 ...
'filter_condition_callback' => array($this, '_selectedCustomerFilter'),
 ));

I.e. filtering should be done by the _selectedCustomerFilter() in the selected_customers column:

protected function _selectedCustomerFilter($collection, $column)
 {
 $filter = $this->getRequest()->getParam('filter', null);
 $filter_data = Mage::helper('adminhtml')->prepareFilterString($filter);
 if (!$filter_data || !isset($filter_data['selected_customers'])) {
 return $this;
 }
$selectedCustomers = $this->getSelectedCustomers();
 if (!$selectedCustomers || !is_array($selectedCustomers)) {
 return $this;
 }
if ($filter_data['selected_customers'] == '1') {
 $operator = 'IN';
 } else {
 $operator = 'NOT IN';
 }
 $collection->getSelect()->where('e.entity_id ' . $operator . ' (' . implode(',', $selectedCustomers) . ')');
return $this;
 }

 

Summary

This example has shown us that we can easily satisfy such client needs when a new menu, a new form, a new grid or dynamic tabs should be created. We can also use existing collections or custom database models. Magento provides a tremendous amount of help throughout the process, it holds many core classes that we only need to either implement or complement. If you think this article can be useful to other readers as well, please share it. You can also write your comments below. If you have any queries, please don’t hesitate to comment.

 

174 replies
  1. Substance Abuse Dsm 5 says:

    Alcohol Abuse Therapist http://aaa-rehab.com Drug Rehab http://aaa-rehab.com Women’S Rehab Near Me
    http://aaa-rehab.com

  2. Hyon Prattis says:

    I simply want to mention I’m new to blogs and seriously loved your web page. Probably I’m planning to bookmark your blog post . You amazingly come with outstanding posts. With thanks for sharing with us your blog site.

  3. cannabidol says:

    I simply wanted to thank you a lot more for your amazing website you have developed here. It can be full of useful tips for those who are actually interested in this specific subject, primarily this very post. Your all so sweet in addition to thoughtful of others and reading the blog posts is a great delight in my opinion. And thats a generous present! Dan and I usually have enjoyment making use of your recommendations in what we need to do in the near future. Our checklist is a distance long and tips will certainly be put to excellent use.

  4. John Deere Diagnostic and Test Manuals says:

    I wanted to thank you once again for your amazing web-site you have made here. It is full of useful tips for those who are truly interested in this specific subject, specifically this very post. You really are all really sweet as well as thoughtful of others and also reading your blog posts is a superb delight in my opinion. And thats a generous surprise! Ben and I are going to have enjoyment making use of your recommendations in what we must do in a few days. Our list is a mile long so your tips might be put to beneficial use.

  5. cbd vape oil 500mg for sale near me says:

    I discovered your blog site on google as well as inspect a few of your very early blog posts. Continue to keep up the great run. I simply extra up your RSS feed to my MSN Information Reader. Looking for ahead to learning more from you in the future!?

  6. John Deere Repair Manuals says:

    Can I just say what a relief to discover somebody that truly knows what theyre speaking about online. You certainly discover how to bring a difficulty to light making it crucial. Workout . should ought to see this and understand why side of the story. I cant believe youre not more well-liked since you also certainly develop the gift.

  7. what cbd is good for dog that gets seizures says:

    An outstanding share, I just given this onto a colleague who was doing a little analysis on this. As well as he actually got me morning meal due to the fact that I found it for him. smile. So let me rephrase that: Thnx for the treat! But yeah Thnkx for investing the time to discuss this, I really feel strongly concerning it as well as like finding out more on this subject. When possible, as you end up being know-how, would you mind upgrading your blog site with even more details? It is very valuable for me. Large thumb up for this post!

  8. cbd dog treats in wichita says:

    This web site is really a walk-through for every one of the info you wanted concerning this and also didn?t know that to ask. Glimpse below, as well as you?ll most definitely discover it.

  9. click here for more info says:

    Can I simply say what a relief to discover someone that really understands what theyre speaking about online. You most definitely know just how to bring an issue to light as well as make it essential. More individuals need to read this and comprehend this side of the story. I angle think youre not more popular due to the fact that you absolutely have the gift.

  10. Gertha Selis says:

    An impressive share, I just offered this onto a colleague that was doing a little evaluation on this. And also he as a matter of fact purchased me breakfast because I discovered it for him. smile. So let me reword that: Thnx for the reward! However yeah Thnkx for investing the time to review this, I really feel highly concerning it and also enjoy learning more on this subject. If possible, as you become know-how, would you mind upgrading your blog site with even more information? It is very useful for me. Large thumb up for this blog post!

  11. Deetta Shwab says:

    There are some fascinating moments in this short article yet I don?t know if I see every one of them facility to heart. There is some validity yet I will certainly take hold viewpoint till I check out it further. Great short article, many thanks and also we want a lot more! Added to FeedBurner also

  12. pop over to this website says:

    There are certainly a lot of information like that to take into consideration. That is a great point to bring up. I provide the ideas over as basic inspiration yet plainly there are questions like the one you raise where the most crucial point will certainly be operating in honest good faith. I don?t know if ideal methods have emerged around points like that, however I make sure that your job is clearly identified as a level playing field. Both boys as well as women really feel the effect of simply a moment?s satisfaction, for the rest of their lives.

  13. visit the site says:

    Aw, this was a really nice article. In concept I want to place in creating like this additionally? taking some time and real initiative to make an excellent post? yet what can I claim? I hesitate alot and by no means seem to get something done.

  14. click here to investigate says:

    I was very delighted to locate this web-site. I wanted to thanks for your time for this fantastic read!! I most definitely enjoying every little of it as well as I have you bookmarked to check out brand-new stuff you post.

  15. talking to says:

    An excellent share, I just provided this onto an associate who was doing a little evaluation on this. And he as a matter of fact acquired me breakfast because I found it for him. smile. So let me reword that: Thnx for the reward! However yeah Thnkx for investing the moment to discuss this, I feel highly concerning it and also enjoy finding out more on this subject. When possible, as you become knowledge, would you mind upgrading your blog with more details? It is extremely valuable for me. Large thumb up for this article!

  16. their explanation says:

    I?d have to contact you here. Which is not something I usually do! I enjoy reviewing a post that will certainly make people assume. Also, many thanks for permitting me to comment!

  17. one-time offer says:

    Can I simply say what a relief to locate someone who in fact knows what theyre talking about on the net. You absolutely know exactly how to bring a concern to light and make it crucial. More individuals require to read this as well as recognize this side of the story. I angle think youre not much more preferred due to the fact that you most definitely have the present.

  18. at Bing says:

    After research study a few of the post on your website now, and also I truly like your method of blog writing. I bookmarked it to my book marking site list and also will certainly be inspecting back quickly. Pls look into my web site as well and also let me understand what you assume.

  19. GFE phone sex says:

    My brother suggested I would possibly like this web site. He was once entirely right. This post truly made my day. You cann’t consider simply how a lot time I had spent for this information! Thanks!

  20. article says:

    Aw, this was a really wonderful message. In suggestion I would like to put in writing like this additionally? requiring time as well as real initiative to make an excellent post? but what can I state? I postpone alot and also never seem to get something done.

  21. image source says:

    I?d have to consult you below. Which is not something I typically do! I enjoy reviewing an article that will make individuals believe. Additionally, thanks for allowing me to comment!

  22. security screens home depot says:

    Greetings from Florida! I’m bored at work so I decided to browse your blog on my iphone during lunch break. I really like the knowledge you provide here and can’t wait to take a look when I get home. I’m surprised at how fast your blog loaded on my mobile .. I’m not even using WIFI, just 3G .. Anyways, good site!

  23. replacement screens for security doors says:

    I am really loving the theme/design of your website. Do you ever run into any browser compatibility problems? A number of my blog audience have complained about my blog not operating correctly in Explorer but looks great in Chrome. Do you have any ideas to help fix this problem?

  24. security screens doors says:

    Hi would you mind sharing which blog platform you’re using? I’m looking to start my own blog soon but I’m having a difficult time deciding between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your design and style seems different then most blogs and I’m looking for something completely unique. P.S My apologies for getting off-topic but I had to ask!

  25. buy cbd dabs online says:

    I discovered your blog site on google as well as inspect a few of your early messages. Remain to maintain the excellent run. I just additional up your RSS feed to my MSN News Reader. Looking for ahead to learning more from you later on!?

  26. text stlye says:

    Hi there fantastic website! Does running a blog similar to thisrequire a great deal of work? I have absolutely no knowledge of programming but I was hoping to startmy own blog in the near future. Anyway, if you have any suggestions or tipsfor new blog owners please share. I understand this is off topic nevertheless I just had to ask.Cheers!

  27. cbd edibles virginia says:

    An excellent share, I simply provided this onto a coworker who was doing a little evaluation on this. And he as a matter of fact purchased me breakfast because I located it for him. smile. So let me reword that: Thnx for the treat! However yeah Thnkx for spending the moment to review this, I really feel strongly regarding it and also enjoy reading more on this subject. When possible, as you end up being expertise, would you mind updating your blog with even more information? It is extremely helpful for me. Large thumb up for this article!

  28. cbd oil for pets vs humans says:

    A remarkable share, I simply offered this onto an associate who was doing a little analysis on this. And also he in fact acquired me breakfast since I found it for him. smile. So let me reword that: Thnx for the reward! Yet yeah Thnkx for spending the time to discuss this, I feel strongly regarding it as well as enjoy reading more on this subject. When possible, as you become competence, would certainly you mind upgrading your blog with more details? It is highly useful for me. Large thumb up for this article!

  29. Shirley Bilek says:

    This website is truly a walk-through for every one of the information you wanted regarding this and didn?t understand that to ask. Look here, and also you?ll absolutely uncover it.

  30. viagra prices says:

    You made some good points there. I looked on the web for the problem and found most individuals will certainly accompany with your site.

  31. buy viagra over the counter in usa says:

    Oh my goodness! an amazing post guy. Thanks Nevertheless I am experiencing issue with ur rss. Don?t understand why Incapable to register for it. Is there anybody getting the same rss trouble? Anybody that recognizes kindly react. Thnkx

  32. effectiveness of generic viagra says:

    There are certainly a great deal of information like that to take into consideration. That is a wonderful indicate bring up. I supply the thoughts over as basic ideas but plainly there are concerns like the one you raise where the most crucial point will be operating in straightforward good faith. I don?t recognize if finest methods have actually arised around things like that, yet I make certain that your task is plainly recognized as an up for grabs. Both kids and women really feel the effect of simply a moment?s enjoyment, for the rest of their lives.

  33. does viagra help premature ejaculation says:

    A remarkable share, I just offered this onto a coworker who was doing a little evaluation on this. And also he as a matter of fact purchased me morning meal because I discovered it for him. smile. So let me reword that: Thnx for the treat! But yeah Thnkx for spending the moment to review this, I really feel strongly about it and also love reading more on this subject. Preferably, as you come to be expertise, would you mind updating your blog with even more information? It is extremely useful for me. Huge thumb up for this blog post!

  34. viagra on line no prescription says:

    When I initially commented I clicked the -Notify me when new remarks are added- checkbox and also currently each time a remark is included I get 4 e-mails with the same remark. Exists any way you can remove me from that solution? Many thanks!

  35. viagra for woman its not just me says:

    Aw, this was a really wonderful blog post. In concept I wish to put in creating similar to this additionally? requiring time and actual effort to make an excellent article? however what can I say? I postpone alot and by no means seem to obtain something done.

  36. free v bucks says:

    Hello, i feel that i saw you visited my blog thus
    i got here to return the prefer?.I’m trying to find issues to enhance my site!I assume its good
    enough to make use of some of your concepts!!

  37. sextxing says:

    I do agree with all of the concepts you have presented for your post. They’re really convincing and will definitely work. Nonetheless, the posts are very brief for novices. May just you please extend them a little from subsequent time? Thank you for the post.

  38. best digital marketing company in mangalore says:

    Hello terrific blog! Does running a blog similar to this require a great deal of work? I have absolutely no expertise in coding but I had been hoping to start my own blog in the near future. Anyway, if you have any recommendations or techniques for new blog owners please share. I understand this is off topic nevertheless I simply needed to ask. Thank you!

  39. digital marketing in mangalore says:

    Hey there! I know this is kind of off topic but I was wondering which blog platform are you using for this website? I’m getting tired of WordPress because I’ve had issues with hackers and I’m looking at alternatives for another platform. I would be great if you could point me in the direction of a good platform.

  40. cbd oil gets me high says:

    I?m impressed, I have to say. Really hardly ever do I encounter a blog site that?s both educative as well as enjoyable, as well as let me tell you, you have actually struck the nail on the head. Your concept is superior; the problem is something that insufficient individuals are talking smartly about. I am very pleased that I came across this in my search for something relating to this.

  41. free spins coin master says:

    With havin so much content do you ever run into any problems of plagorism or copyright violation? My site has a lot of completely unique content I’ve either created myself or outsourced
    but it appears a lot of it is popping it up all over the web without my agreement.
    Do you know any solutions to help prevent content from being stolen? I’d truly appreciate it.

  42. free robux generator says:

    Just wish to say your article is as surprising.
    The clearness on your publish is simply nice and that i could think you
    are an expert on this subject. Fine together with your permission let
    me to clutch your feed to keep updated with forthcoming
    post. Thank you a million and please continue the gratifying work.

  43. hack brawl stars says:

    Hi there, just became aware of your blog through Google, and found that it’s truly
    informative. I am gonna watch out for brussels. I will appreciate if you continue this
    in future. A lot of people will be benefited from your writing.
    Cheers!

  44. discover here says:

    This internet site is actually a walk-through for all of the details you desired concerning this and also didn?t recognize who to ask. Glance here, and also you?ll most definitely discover it.

  45. LigaZ says:

    การทุกท่านต้องการสัมผัสประสบการณ์การเล่นคาสิโนออนไลน์ คาสิโนออนไลน์ อย่างเพลิดเพลินและไม่เหมือนใคร สามารถสมัครสมาชิก คาสิโนออนไลน์ เพื่อเข้าร่วมเดิมพันได้บนเว็บไซต์ของเรา

  46. ลิ้งดูบอล says:

    In order to boost traffic, Happy New Casino Casino blog must be focused on providing good quality and engaging content. Happy New Casino Casino readers will be happy to return if the information Happy New Casino AllForBet provide is factual, informative and fun to read.

  47. Vegus says:

    Don’t say hurtful or offensive things to him as a mad person will have a tendency to go overboard.

  48. free says:

    I always emailed this webpage post page to all my friends, as
    if like to read it afterward my friends will too.

  49. เกมการพนัน says:

    Save the battery life on your Casino by turning off Notifications and Location Services until you need to use them. Your Casino will automatically reach out and update these functions regularly and use battery power in the process. Be aware of the power your Casino is using, and you will have it when you need it.

  50. Boss Security Screens says:

    Sweet blog! I found it while searching on Yahoo News. Do you have any tips on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Many thanks

  51. Therese Oya says:

    Can I just claim what a relief to locate someone that in fact understands what theyre speaking about on the web. You most definitely know how to bring a concern to light and also make it essential. More individuals need to read this as well as recognize this side of the story. I angle believe youre not a lot more prominent because you certainly have the gift.

  52. แทงบอล says:

    Thank you for the sensible critique. Me & my neighbor were just preparing to do come research in it. We got a grab a book from our area library but I think I learned more from it post. I am very glad to see such excellent info being shared freely out there.

  53. Herma Tremore says:

    The following time I check out a blog, I really hope that it does not dissatisfy me as high as this set. I imply, I understand it was my choice to check out, but I really thought youd have something interesting to say. All I hear is a bunch of whimpering concerning something that you might deal with if you werent as well hectic searching for attention.

  54. avast driver updater license key says:

    Hello there, I discovered your web site by means
    of Google whilst searching for a similar topic, your web site came up, it appears good.
    I’ve bookmarked it in my google bookmarks.
    Hi there, simply changed into alert to your weblog thru
    Google, and located that it’s really informative. I’m going to
    be careful for brussels. I will be grateful if you happen to proceed this in future.

    Lots of folks shall be benefited from your writing.
    Cheers!

  55. avast activation code says:

    It’s appropriate time to make a few plans for the
    longer term and it is time to be happy. I’ve read this publish
    and if I may just I desire to counsel you few fascinating things
    or advice. Perhaps you could write subsequent articles regarding this article.
    I want to learn even more issues about it!

  56. free spins coin master says:

    Hi there, I found your site by the use of Google at the same time as looking for a related subject, your
    website got here up, it seems good. I have bookmarked it in my google bookmarks.

    Hi there, simply changed into aware of your blog through Google, and
    located that it’s truly informative. I am going to be careful for brussels.
    I’ll be grateful in the event you continue this in future.
    Many other folks will probably be benefited from your writing.
    Cheers!

  57. cialis canada price says:

    Hi! I simply would love to give a substantial thumbs up for the excellent info you have right here on this blog post. I will be coming back to your blog for even more quickly.

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published.