Ext.override – Monkey Patching Ext JS
July 24, 2009 18 Comments
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.
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?
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.
Thanks for the explanation
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
Brilliant!
Strange the override framework doesn’t support the base class. Great workaround!
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.
what is the difference of Ext.override and Ext.apply ?
thanks.
@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
});
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.. 🙂
Pingback: » Ext.override-ın istifadəsi PHP, Javascript, Ext JS və s. …
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.
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
}
});
})();
Hi guys i finally saw my problem
It seems as i can not override EVENT hrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr but just FUNCTIONS.
thanks
Pingback: extjstutorial.org
Pingback: extjstutorial.org
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!
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.
i cound’t understand this {functioname}.apply(this , arguments) , how ‘apply’ method is working on function ?