Pages

Sunday, June 30, 2013

How to add Javascript to a Magento Admin page (AKA: How to Override Magento Blocks)

Recently I had to add some additional Javascript validation to a core part of the Magento Admin, and I thought I’d share the best way to do this without having to modify core files.

Because I often have to modify small parts of default Magento functionality, I have created a module that exists for the sole purpose of overriding models and blocks. In this post I’ll go through the steps required to override blocks properly, without modifying core code. The process for models is almost identical. I’m going to use as an example the block that I was required to override: Mage_Adminhtml_Block_Promo_Quote_Edit. All I want to do is add some additional Javascript to the page that hijacks the “Save” event and asks the user if they are sure.

First things first: build a custom module (or pick an existing one) to work from.

in {namespace}/{modulename}/etc/config.xml, add the following:

<config>
   ...
   <global>
      ...
      <blocks>
         <adminhtml>
            <rewrite>
               <promo_quote_edit>{namespace}_{modulename}_Block_Adminhtml_Promo_Quote_Edit</promo_quote_edit>
            </rewrite>
         </adminhtml>
      </blocks>
      ...
   </global>
   ...
</config>

What we’ve just done is tell Magento that when it looks for the block identified as “adminhtml/promo_quote_edit“, load this block class: {namespace}_{modulename}_Block_Adminhtml_Promo_Quote_Edit

We are therefore required to define this class. We do so in path that the class suggests. In this case, it’s: app/code/local/{namespace}/{modulename}/Block/Adminhtml/Promo/Quote/Edit.php. Create this file, and write the following:

<?php
    class {namespace}_{modulename}_Block_Adminhtml_Promo_Quote_Edit
        extends Mage_Adminhtml_Block_Promo_Quote_Edit
    {

By using “extends” and giving the class name of the original block, our new class inherits all of the functions and variables of it’s parent class. If we left the file like this, Magento would act no differently from a user’s perspective.

To give that block new functionality, add as many new functions as you like. But to override a function, as I am doing here, redefine that function within your new class. One very important thing to remember, however, is to ensure that any overridden functions perform the same tasks as the parent, or you risk interfering unintentionally with Magento’s core functionality.

I want to add more Javascript, and I happen to know that Javascript is added into the $_formScripts variable that belongs to this block. I also know that Javascript tends to be added on __construct(). To ensure the class acts the same way as it always did, I define the __construct function like this:

<?php
    public function __construct()
    {
        parent::__construct();
       
        $this->_formScripts[] = "
            editForm.secondarySubmit = editForm.submit;
            editForm.submit = function(url) {
                if (document.getElementById('rule_coupon_type').value == 1) {
                    var answer = confirm('WARNING: This price rule has no Coupon Code.
                    Are you sure you want to do this?');
                } else {
                    var answer = true;
                }
                if (answer) {
                    editForm.secondarySubmit(url);
                } else {
                    return false;
                }
            }
        ";
    }
?>

Note the parent::__construct(); call, that will run the __construct() function of Mage_Adminhtml_Block_Promo_Quote_Edit

In this case, the Javascript I added uses the prototype library to redefine what happens when the form is saved.

Pretty simple really!

No comments:

Post a Comment