atwix

View product button on the product edit page in Magento admin

Hello dear friends. While working with Magento, many of you may have noticed that, when you manage products in the admin you need to see how the product looks on the frontend. Of course, you can open a new page, then open frontend search or write direct url address to this product page, as Magento does not have the button or direct link from the admin page to the frontend product page, but it is not very simple way. Let’s create module with this feature. And best of all will be adding a button to the product edit page in the admin near ‘save’, ‘back’, etc… At first, we should find in what file the code, that responses for rendering these buttons, is located. It is the file app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php – hooray, we have found it! Afterwards, we need to rewrite this block functionality and below you can see how to implement this with config.xml file.

<?xml version="1.0"?>
<config>
    <modules>
        <Atwix_PVF>
            <version>0.0.1</version>
        </Atwix_PVF>
    </modules>
    <frontend>
    </frontend>
    <global>
        <blocks>
            <atwix_pvf>
                <class>Atwix_PVF_Block</class>
            </atwix_pvf>
            <adminhtml>
                <rewrite>
                    <catalog_product_edit>Atwix_PVF_Block_Adminhtml_Catalog_Product_Edit</catalog_product_edit>
                </rewrite>
            </adminhtml>
        </blocks>
    </global>
</config>

At the following step is necessary to create the file app/code/local/Atwix/PVF/Block/Adminhtml/Catalog/Product/Edit.php that will contain next code:

class Atwix_PVF_Block_Adminhtml_Catalog_Product_Edit extends Mage_Adminhtml_Block_Catalog_Product_Edit
{
    /**
     * @var Mage_Catalog_Model_Product Product instance
     */
    private $_product;

    /**
     * Preparing global layout
     * 
     * @return Atwix_PVF_Block_Adminhtml_Catalog_Product_Edit|Mage_Core_Block_Abstract
     */
    protected function _prepareLayout()
    {
        parent::_prepareLayout();
        $this->_product = $this->getProduct();
        $this->setChild('view_on_front',
            $this->getLayout()->createBlock('adminhtml/widget_button')
                ->setData(array(
                'label'     => Mage::helper('catalog')->__('View Product Page'),
                'onclick'   => 'window.open(\''.Mage::getModel('core/url')->getUrl() . $this->_product->getUrlPath() .'\')',
                'disabled'  => !$this->_isVisible(),
                'title' => (!$this->_isVisible())?
                    Mage::helper('catalog')->__('Product is not visible on frontend'):
                    Mage::helper('catalog')->__('View Product Page')
            ))
        );

        return $this;
    }

    /**
     * Returns duplicate & view on front buttons html
     * 
     * @return string
     */
    public function getDuplicateButtonHtml()
    {
        return $this->getChildHtml('duplicate_button') . $this->getChildHtml('view_on_front');
    }

    /**
     * Checking product visibility
     * 
     * @return bool
     */
    private function _isVisible()
    {
        return $this->_product->isVisibleInCatalog() && $this->_product->isVisibleInSiteVisibility();
    }

}

Onwards, let’s get across the class logic described above. We guess, you have already found out that private variable $_product is needed for us to load product instance into it.
The functional, that responses for rendering buttons, is located in _prepareLayout function, so it must be overridden, but don’t omit to call parent: _prepareLayout, because a lot of functionality will be lost. Following on – after parent calling we add the child element with id ‘view_on_front’ and instance of the button widget object. But what is this? Oh.. no! Magento can’t render children with the custom id. Maybe function that renders other button can help us. That is it.
We choose getDuplicateButtonHtml function, this one returns html of duplicated button, so we add our button html to this function return param. As the result, we get useful button that allows us to open the product page just clicking it.
Thank you for attention, stay tuned.

UPDATE: We’ve found another good way to add such button on product page in admin. As my fellow wrote in his article Advices and Best Practices for Magento developers we should avoid any rewrites in the modules, as rewrites cause conflicts between modules.
But what should we use instead of block rewrite? – It’s observer. In our case it’s called `adminhtml_block_html_before `, and see below how our config.xml will be changed:

<?xml version="1.0"?>
<config>
    <modules>
        <Atwix_PVF>
            <version>0.0.1</version>
        </Atwix_PVF>
    </modules>
    <global>
        <blocks>
            <atwix_pvf>
                <class>Atwix_PVF_Block</class>
            </atwix_pvf>
        </blocks>
        <models>
            <atwix_pvf>
                <class>Atwix_PVF_Model</class>
            </atwix_pvf>
        </models>
    </global>
    <adminhtml>
        <events>
            <adminhtml_block_html_before>
                <observers>
                    <atwix_pvf>
                        <type>model</type>
                        <class>Atwix_PVF_Model_Observer</class>
                        <method>addPVFButton</method>
                    </atwix_pvf>
                </observers>
            </adminhtml_block_html_before>
        </events>
    </adminhtml>
</config>

However, there’s one issue – this observer is called many times for every blocks in the admin. So we need to add checking by block type. Block type should be equal ‘adminhtml/catalog_product_edit’. Let’s look into observer code to see how this issue has been resolved:

class Atwix_PVF_Model_Observer
{
    public function addPVFButton($observer)
    {
        $_block = $observer->getBlock();
        $_type = $_block->getType();
        if ($_type == 'adminhtml/catalog_product_edit') {
            $_deleteButton = $_block->getChild('delete_button');
            $_block->setChild('product_view_button',
                $_block->getLayout()->createBlock('atwix_pvf/adminhtml_widget_button')
            );
            $_deleteButton->setBeforeHtml($_block->getChild('product_view_button')->toHtml());
        }
    }
}

In previous code snippet we got HTML of delete button and tied our button’s HTML to it.

And finally, we’ve created a block for this button:

class Atwix_PVF_Block_Adminhtml_Widget_Button extends Mage_Adminhtml_Block_Widget_Button
{
    /**
     * @var Mage_Catalog_Model_Product Product instance
     */
    private $_product;

    /**
     * Block construct, setting data for button, getting current product
     */
    protected function _construct()
    {
        $this->_product = Mage::registry('current_product');
        parent::_construct();
        $this->setData(array(
            'label'     => Mage::helper('catalog')->__('View Product Page'),
            'onclick'   => 'window.open(\''.Mage::getModel('core/url')->getUrl() . $this->_product->getUrlPath() .'\')',
            'disabled'  => !$this->_isVisible(),
            'title' => (!$this->_isVisible())?
                Mage::helper('catalog')->__('Product is not visible on frontend'):
                Mage::helper('catalog')->__('View Product Page')
        ));
    }

    /**
     * Checking product visibility
     *
     * @return bool
     */
    private function _isVisible()
    {
        return $this->_product->isVisibleInCatalog() && $this->_product->isVisibleInSiteVisibility();
    }
}

Latest version of the module was uploaded to our GitHub account
We hope this article’s update will be useful.



Enjoyed this post? us on Facebook and on Twitter to stay tuned.

  • Simon Sprankel

    Good idea. Inchoo did something similar some time ago: http://inchoo.net/ecommerce/magento/view-product-in-frontend-from-magento-admin/
    Anyway, I would prefer a solution which does not need a rewrite but uses events instead. Don’t you think this is possible?

    • NickKravchuk

      yes, it is possible, going to update this article in a few days, will describe how to do this using observers, stay tuned, thanks

      • Simon Sprankel

        Cool, thanks. Would also love to see a GitHub repo for the extension ;)

        • NickKravchuk

          The article has been updated, also added link to GitHub repo, check it out :)

  • Scott

    I’m getting 500 errors when using this button. The button takes me to /jade-403-pva-glue-4-ounces.html instead of /bookbinding-supplies/adhesives/pva-glue-jade/jade-403-pva-glue-4-ounces.html when clicked. The page with the categories works, but the page it is sending me to just 500′s. Any ideas?

    • NickKravchuk

      Hi Scott, you know that product may belong to the multiple categories, so module doesn’t use category url key, but it works for us, anyway you should look into the magento var/log/ folder or in apache log to see the error.