Ext.override – Monkey Patching Ext JS
July 24, 2009 by Ed Spencer · 5 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!