Ext.override – Monkey Patching Ext JS

Ext JS contains a function called Ext.override. Using this function allows you to add functionality to existing classes, as well as override properties of the class. For example, let’s say we want to override how Ext.Windows are hidden:

Ext.override(Ext.Window, {
  hide: function() {
    //the contents of this function are now called instead of the default window hide function
  }
});

Using Ext.override changes the prototype of the class you are overriding – all instances of Ext.Window will now use the new hide function in the example above.

Overriding other classes can be dangerous, especially when they are classes from a library not under your control. For example, if the Ext.Window class was refactored in a later version, your overrides may no longer work. In some situations you might choose to go down the safer route of augmenting the existing functionality without overriding it. Here’s one way we can achieve this using a closure:

(function() {
  var originalHide = Ext.Window.prototype.hide;

  Ext.override(Ext.Window, {
    hide: function() {
      //perform pre-processing
      alert("The window is about to close!");

      //call the original hide function
      originalHide.apply(this, arguments);

      //perform post-processing.
      alert("The window closed!!1");
    }
  });
})();

In the example above we set up a closure via an anonymous function which is executed immediately. This lets us keep a reference to the original hide function on Ext.Window. Underneath we perform the override itself, in which we provide our own logic.

The originalHide.apply(this, arguments) line is key to maintaining Ext.Window’s original functionality. By using the apply keyword with the Window’s usual scope (‘this’) and the function’s arguments ‘array’, we can wrap our functionality before or after the original method.

Augmenting in this way is safer than simply overwriting the function, or copy & pasting Ext.Window’s original hide function into your own, as you don’t have to worry about breaking what Ext JS itself does (you’re still responsible for making sure your own additions work after upgrading Ext though).

Be aware that this will affect all instances of Ext.Window (or whatever class you are overriding). If that isn’t what you want, use Ext.extend to create your own subclasses instead.

Finally, note that you can use Ext.override on any class, not just the built-in Ext ones – all it does internally is call Ext.apply on the constructor function’s prototype.

18 Responses to Ext.override – Monkey Patching Ext JS

  1. andycramb says:

    Ed interesting pos, I never thought about the backwards compatibility of future releases.In the case above could you not just use Ext.extend instead of override? What is the diffrence in the case above?

  2. Edward Spencer says:

    You could indeed use Ext.extend instead, which is often the best choice.It comes down to whether you want the functionality to affect all instances of a given class or not.Where I have found this most useful is in extending some base Grid classes I have. I have a default extended Grid class, which provides a default top toolbar. I reuse this across applications, but on one app I wanted to add an extra button to every grid, without losing the others. Here is the code I used to do that.This transparently augments the functionality of my ExtMVC.view.scaffold.Index class, without requiring me to create an extension and change all of the class names in my code. The hasPrintButton property allows each grid to opt out of having the extra button.

  3. andycramb says:

    Thanks for the explanation

  4. Steffen Hiller says:

    Nice post!This pattern pretty much mimics the behaviour of Ruby's Module::alias_method method.Will definitely keep that pattern in mind for the future. Sometimes you have to monkey patch Ext JS though, when trying to change a behaviour of methods that can't be manipulated by pre–processing instance variables or method arguments or post-processing method return values.Thanks & Cheers,Steffen

  5. jasbury says:

    Brilliant!
    Strange the override framework doesn’t support the base class. Great workaround!

  6. Andreas Waschinski says:

    Just a quick note as I came across this posting.

    As long as you don’t need to run own code both before and after the default implementation using createInterceptor and createSequence would be the easier approach.

  7. Primadi Setiawan says:

    what is the difference of Ext.override and Ext.apply ?
    thanks.

  8. Ed Spencer says:

    @Primadi Ext.apply modifies a normal object, Ext.override modifies a ‘class’ prototype. Usually this means that you’ll use .apply on an instance and .override on a class:

    var myWindow = new Ext.Window({});
    Ext.apply(myWindow, {some: ‘other property’});

    //makes all new Ext.Window instances have closable: false set
    Ext.override(Ext.Window, {
    closable: false
    });

  9. Primadi Setiawan says:

    I try this, and the result is same:

    Method1:
    Ext.override(Ext.Window, {
    closable: false
    });

    Method2:
    Ext.apply(Ext.Window.prototype, {
    closable: false
    });

    But, i know the point: ExtJS try to hide prototype object,
    because it is confusing for new comer in javascript.

    Thanks for your explanation.. 🙂

  10. Pingback: » Ext.override-ın istifadəsi PHP, Javascript, Ext JS və s. …

  11. marcel says:

    Hi everyone

    When i override a class, where should i put the code (the file)?

    I have override native extjs.TabPanel.tabchange event.

    Here is my JS file structure
    JS
    |
    |_Librairies
    |
    |_extjs
    |
    |_Views (All my modules)
    |
    |_module1( i have custom .js file in each module)

    Q: Where should i put the overriding code so it will change all tabchange events ?

    Thanks.

  12. marcel says:

    Hi i want to manage tabChange histories in my application. I’ve followed your examples, but nothing happens. What i’m doing wrong ?

    The ‘tabchange’ event doesn’t execute the ovrride function.

    I know there is something wrong with the reference of the ‘originalTabChange.apply()’, but it’s not my problem for now.

    Could somebody, please, tell me why my override function doesn’t execute ?

    Thanks

    ——Here is the code ——
    (function(){
    //Get a reference to the original tabchange function
    var originalTabChange = Ext.TabPanel.prototype.tabchange;
    Ext.override(Ext.TabPanel, {
    tabchange: function(myself, tab){
    debugger; // —————————–Nothing happen 😦
    //perform post-processing.
    Ext.MessageBox.alert(“Tab changed and here are arguments. [from: ” + myself.id + “, to: “+ tab.id +”]”);

    //call the original tabchange function
    originalTabChange.apply(this, arguments); /// ??????????

    /code for /extras functionalities that i want for all TABPANEL in my application
    }
    });
    })();

  13. marcel says:

    Hi guys i finally saw my problem

    It seems as i can not override EVENT hrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr but just FUNCTIONS.

    thanks

  14. Pingback: extjstutorial.org

  15. Pingback: extjstutorial.org

  16. billy b says:

    Awesome post! I was trying to use Ext.grid.Panel.reconfigure() and it led to an error in Ext.selection.RowModel

    var view = this.views;
    var viewLn = views.length;

    where it was trying to get the length of an internal array it hadn’t initialized yet. I was really stressing about how to work around it. Now I just add:

    Ext.selection.RowModel.override({views:[]});

    to my application.js (following MVC), and it fixes the problem. Plus it provides me a singular place place to put my Ext “patches” so that I can remove them easily if Sencha fixes the problems.

    Thanks!

  17. John says:

    Excelent post :), i have a question : If I have a chart and I want that legends are clickable, which would be the best way to achieve this? Thx Ed.

  18. Thirunavkkarasu says:

    i cound’t understand this {functioname}.apply(this , arguments) , how ‘apply’ method is working on function ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: