3

I want to add the "Company" column from the customer's Address attributes.

Is there any way to populate this column through an observer or do I need to extend the prepareCollection or preparePage functions?


Working Code:

Observer is set up on event core_block_abstract_prepare_layout_before


XML

/app/code/local/Mbs/Changegrid/etc/config.xml
<?xml version="1.0"?>
<config>
    <modules>
        <Mbs_Changegrid>
            <version>0.4.0</version>
        </Mbs_Changegrid>
    </modules>
    <global>
        <models>
            <mbs_changegrid>
                <class>Mbs_Changegrid_Model</class>
            </mbs_changegrid>
        </models>
    </global>
    <adminhtml>
        <events>
            <core_block_abstract_to_html_before>
                <observers>
                    <changegrid_before_block>
                        <class>Mbs_Changegrid_Model_Observer</class>
                        <method>beforeBlockToHtml</method>
                    </changegrid_before_block>
                </observers>
            </core_block_abstract_to_html_before>
            <eav_collection_abstract_load_before>
                <observers>
                    <changegrid_collection_load>
                        <class>Mbs_Changegrid_Model_Observer</class>
                        <method>beforeCollectionLoad</method>
                    </changegrid_collection_load>
                </observers>
            </eav_collection_abstract_load_before>
        </events>
    </adminhtml>
</config>

PHP

/app/code/local/Mbs/Changegrid/Model/Observer.php
class Mbs_Changegrid_Model_Observer {
    public function beforeBlockToHtml(Varien_Event_Observer $observer) {
        $grid = $observer->getBlock();
        /**
         * Mage_Adminhtml_Block_Customer_Grid
         */
        if ($grid instanceof Mage_Adminhtml_Block_Customer_Grid) {
            $grid->addColumnAfter(
                'company',
                array(
                    'header' => Mage::helper('customer')->__('Company'),
                    'index'  => 'company'
                ),
                'name'
            );
        }
    }

    public function beforeCollectionLoad(Varien_Event_Observer $observer) {
        $collection = $observer->getCollection();
        if (!isset($collection)) {
            return;
        }

        /**
         * Mage_Customer_Model_Resource_Customer_Collection
         */
        if ($collection instanceof Mage_Customer_Model_Resource_Customer_Collection) {
            /* @var $collection Mage_Customer_Model_Resource_Customer_Collection */
            $collection->addAttributeToSelect('company');
            $addressCollection = Mage::getModel('customer/address')->getCollection()->addAttributeToSelect('company');
            $addressCollection->getSelect()->limit(1);
            $address = $addressCollection->getFirstItem();
            foreach ($address->getAttributes() as $attribute) {
                if (is_null($attribute->getAttributeID()) || is_null($attribute->getFrontendLabel()) || ($attribute->getFrontendLabel() == '')) {
                    continue;
                }
                $collection->joinAttribute($attribute->getName(), 'customer_address/' . $attribute->getName(), 'default_billing', null, 'left');
            }
        }
    }
}
9

2 Answers 2

9

It is possible thru rewrite or observer: (observer is better to prevent rewrite conflicts)

Using Observer

Configure your 2 observers: loading the column to grid and loading of collection

<adminhtml>
    <events>
        <core_block_abstract_to_html_before>
            <observers>
                <{observer_name}>
                    <class>{namespace}_{module}/observer</class>
                    <method>beforeBlockToHtml</method>
                </{observer_name}>
            </observers>
        </core_block_abstract_to_html_before>
        <eav_collection_abstract_load_before>
            <observers>
                <{observer_name}>
                    <class>{namespace}_{module}/observer</class>
                    <method>beforeCollectionLoad</method>
                </{observer_name}>
            </observers>
        </eav_collection_abstract_load_before>
    </events>
</adminhtml>

Then create your observer class with the methods in the declaration

class {Namespace}_{Module}_Model_Observer
{
    public function beforeBlockToHtml(Varien_Event_Observer $observer)
    {
        $grid = $observer->getBlock();

        /**
         * Mage_Adminhtml_Block_Customer_Grid
         */
        if ($grid instanceof Mage_Adminhtml_Block_Customer_Grid) {
            $grid->addColumnAfter(
                '{column_code}',
                array(
                    'header' => Mage::helper('{Module}_customer')->__('{{column_name}}'),
                    'index'  => '{column_code}'
                ),
                'entity_id'
            );
        }
    }

    public function beforeCollectionLoad(Varien_Event_Observer $observer)
    {
        $collection = $observer->getCollection();
        if (!isset($collection)) {
            return;
        }

        /**
         * Mage_Customer_Model_Resource_Customer_Collection
         */
        if ($collection instanceof Mage_Customer_Model_Resource_Customer_Collection) {
            /* @var $collection Mage_Customer_Model_Resource_Customer_Collection */
            $collection->addAttributeToSelect('{attribute_code}');
        }
    }
}

See this answer: https://magento.stackexchange.com/a/5986/21518

Using Rewrite

Rewrite the grid block's _prepareCollection method and add your column to the collection.

See this answer: https://magento.stackexchange.com/a/5975/21518

3
  • I keep getting fatal error Mage registry key "_singleton/Mbs_Changegrid/observer" already exists. Is this due to the method I had set up previously?
    – travisw
    Commented Jun 26, 2015 at 17:59
  • Yes, you just have to put in the methods if you already have one. Also, please clear the cache. Commented Jun 26, 2015 at 18:32
  • I keep running into this same error, despite several different attempts. I will update my question with the XML to try to find the error.
    – travisw
    Commented Jun 26, 2015 at 18:49
6

No need to rewrite, can all be done in an observer. In the following code, I used the event: adminhtml_block_html_before

The code below is to insert two new columns, called 'Referred By' and a lookup list one for 'State', into the Newsletter Grid.

The idea is the same, and you should be able to use it in your own grid customizations.

1am here now, so just going place the code. ask if you need any clarifications. I did add in some comments ;)

The code also includes a means to fix/enable filtering of the column

I hope this helps.

public function adminhtml_block_html_before(Varien_Event_Observer $observer)
    {

        try {
            $event = $observer->getEvent();
            if ($event->getBlock() instanceof
                Mage_Adminhtml_Block_Newsletter_Subscriber_Grid 
            ) {
                $this->_grid = $event->getBlock();
                $this->_collection = $this->_grid->getCollection();

                /** 
                    YOU COULD ADJUST COLLECTION HERE
                    ADD NEW FIELD FILTERS< COLUMNS ETC **/

                $columnData = array(
                    'header' => 'Referred By',
                    'index'  => 'referred_by',
                    'type'   => 'text',
                );

                $this->_grid->addColumn('referred_by', $columnData);
                $options = array();
                $regions = mage::helper('proxiblue_enhancedsubscription')->getRegionCollection();

                foreach ($regions as $row) {
                    $options[$row['code']] = $row['name'];
                }

                $columnData = array(
                    'header' => 'State',
                    'index'  => 'state',
                    'type' => 'options',
                    'options' => $options,
                    'width' => 400
                );

                $this->_grid->addColumnAfter('state', $columnData, 'lastname');
                $this->_grid->sortColumnsByOrder();
                // rebuild the filters
                $filter = $this->_grid->getParam($this->_grid->getVarNameFilter(), null);
                if (is_null($filter)) {
                    return $this;
                }
                $this->_collection->clear();
                if (is_string($filter)) {
                    $data = $this->_grid->helper('adminhtml')->prepareFilterString($filter);
                    $this->_setFilterValues($data);
                } else {
                    if ($filter && is_array($filter)) {
                        $this->_setFilterValues($filter);
                    }
                }
                // force a reload of the collection
                $this->_collection->load();
            }
        } catch (Exception $e) {
            mage::logException($e);
        }

        return $this;
    }

    protected function _setFilterValues($data)
    {
        foreach ($this->_grid->getColumns() as $columnId => $column) {
            if (isset($data[$columnId]) && (!empty($data[$columnId]) || strlen($data[$columnId]) > 0)
                && $column->getFilter()
            ) {
                $column->getFilter()->setValue($data[$columnId]);
                $this->_addColumnFilterToCollection($column);
            }
        }

        return $this;
    }

    protected function _addColumnFilterToCollection($column)
    {
        if ($this->_collection) {
            $field = ($column->getFilterIndex()) ? $column->getFilterIndex() : $column->getIndex();
            if ($column->getFilterConditionCallback()) {
                call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);
            } else {
                $cond = $column->getFilter()->getCondition();
                if ($field && isset($cond)) {
                    $this->_collection->addFieldToFilter($field, $cond);
                }
            }
        }

        return $this;
    }
2
  • Love this, thank you it is awesome. I've reworked this to my own needs to have a PHP trait with one public method (so far) resetWidgetGridFilters($grid) that takes care of all the reapplying of filters to the grid and collection object. Now in my observer I just add the column, resort the order, and pass the grid object to my PHP trait. One small bug though I think in your current logic is call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);. I think $this->getCollection() is supposed to be $this->_collection. Commented Apr 5, 2016 at 20:15
  • how to make csv export support for this ?
    – hkguile
    Commented Jul 13, 2017 at 5:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.