Question

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');
            }
        }
    }
}
Was it helpful?

Solution

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

OTHER TIPS

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;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top