PDA

View Full Version : [Partial Solution:createInterceptor] Change existing constructors in a proper way



andrei.neculau
31 Aug 2007, 10:53 AM
I have a question regarding modifying constructors.

So.. in order to add or replace ExtJS component's functions or properties, you can use

Ext.apply(Ext.form.Field, {..new info..});But what happens, if I need to modify the constructor of Ext.form.Field? The reason would be that I want to "hack" it's config object upon creation, before calling the superclass constructor.

Remember that I don't want to create another component but keep the same old Ext.form.Field, so that.. for instance Ext.form.TextField will call my newly defined constructor.

Nullity
31 Aug 2007, 11:13 AM
Not sure if this is the cleanest way to do it, but you could try something like this...


myFieldHack = function(config) {
/**
* do your stuff with the config object here
*/

myFieldHack.superclass.constructor.call(this, config);
};

Ext.extend(myFieldHack, Ext.form.Field);
Ext.form.Field = myFieldHack;



EDIT: However, I'm not sure if this will have any effect on the children of Ext.form.Field (i.e. anything that extends it) as they will have already been defined before the code above is called. I'm not totally sure if references are used or if javascript recurses through the hierarchy when the constructor is called, etc. Worth a test I suppose.

Animal
31 Aug 2007, 11:15 AM
You could try comething like:



Ext.form.Field = Ext.form.Field.createInterceptor(function(config){
config.option = "value";
});

Nullity
31 Aug 2007, 11:22 AM
You could try comething like:



Ext.form.Field = Ext.form.Field.createInterceptor(function(config){
config.option = "value";
});


Much better. Please ignore my previous ramblings :">

andrei.neculau
31 Aug 2007, 11:28 AM
Marvelous, Animal!

I actually had to delete my reply to Nullity's first reply!:) I didn't expect such a clean and fast solution.

Too much joy, too soon. It's actually not working. Firebug gives "Ext.form.Field.superclass has no properties"!

andrei.neculau
31 Aug 2007, 11:36 AM
Fixed the error with Ext.form.Field = Ext.extend(Ext.form.Field.createInterceptor(...), Ext.BoxComponent).

But I still don't get it right. I even put a console.log('yes') inside the new function, but nothing shows up on the console, while creating Fields.

Animal
31 Aug 2007, 11:48 AM
OK, The resulting function does not have the prototype and attributes of the original Ext.form.Field.

Try:



Ext.form.Field = Ext.extend(function(config) {
config.option = "value";
}, Ext.form.Field);

Animal
31 Aug 2007, 11:50 AM
Which is basically what nullity suggested :D

andrei.neculau
31 Aug 2007, 12:22 PM
No. That gives excessive recursion because Ext.form.Field's constructor calls it's superclass constructor, which in this case is still Ext.form.Field...

Animal
31 Aug 2007, 12:36 PM
OK, try a special function:



Ext.interceptConstructor = function(c, f) {
var r = function() {
f.apply(this, arguments);
return c.apply(this, arguments);
};
r.superclass = c.superclass;
r.prototype = c.prototype;
return r;
};

Ext.form.Field = Ext.interceptConstructor(Ext.form.Field, function(config) {
config.option = "value";
});

andrei.neculau
31 Aug 2007, 1:13 PM
:) - Thanks for so much energy that you put in this.
Unfortunately, still no... config.option doesn't do it, and neither setting this.option .

LATER EDIT:
I started to get crazy. What if the function is not overwritten at all?
If you put Ext.form.Field = function() {...anything...} then you get a Firebug error that simply states ... and check this: Ext.form.Field.superclass has no properties, and Firebug sends me into the code, where Ext.form.Field is first built by ExtJS. Something like.. the properties and superclass are now gone, but the old constructor reference is still there.

EDIT2: even Ext.form.Field = null doesn't help.

Animal
31 Aug 2007, 1:21 PM
OK, I can't figure it. Im tired now.

Jack! Can you help?

andrei.neculau
31 Aug 2007, 2:28 PM
Very dumm!!!

Not


Ext.form.Field = Ext.form.Field.createInterceptor(function(config){...});But


Ext.form.Field.prototype.constructor = Ext.form.Field.prototype.constructor.createInterceptor(function(config){...});Cheers Animal for the interest!

UPDATE: But it doesn't work on Ext.grid.ColumnModel.prototype.constructor .... ?! So, what's the catch?

andrei.neculau
31 Aug 2007, 11:43 PM
After so many hours of trial, I really cannot figure it out.
With Ext.grid.ColumnModel.prototype.constructor.createInterceptor it doesn't pass through that function altogether.
With your interceptConstructor(Ext.grid.ColumnModel, ..) it works... but then I get an error related to the renderer (when GridView comes into place), so... still wrong somehow.

Anyone with a more agile brain? Someone to notice the mistake, or at least the difference between Ext.form.Field and Ext.grid.ColumnModel when it comes to modifying/intercepting the constructor?

andrei.neculau
1 Sep 2007, 12:06 AM
Animal, Figured out that Ext.interceptConstructor doesn't "copy" the function Ext.grid.ColumnModel.defaultRenderer ... so the columns get no renderer. That's what triggering the error. Any ideas?

LATER EDIT
I had a logic solution, though I don't know how this is the "real solution":

Ext.interceptConstructor = function(c, f) {
var r = function(){
f.apply(this, arguments);
c.apply(this, arguments);
};
r.superclass = c.superclass;
r.prototype = c.prototype;
for (var i in c){
r[i] = c[i];
}
return r;
};

EVEN LATER EDIT
And the difference between using Ext.interceptConstructor on Ext.form.Field.prototype.constructor and Ext.grid.ColumnModel comes from Ext.extend(Ext.form.Field, Ext.BoxComponent, {...});

andrei.neculau
20 Sep 2007, 11:39 PM
Same way - sequenceConstructor


Ext.sequenceConstructor = function(c, f) {
var r = function(){
c.apply(this, arguments);
f.apply(this, arguments);
};
r.superclass = c.superclass;
r.prototype = c.prototype;
for (var i in c){
r[i] = c[i];
}
return r;
};

Animal
21 Sep 2007, 12:03 AM
If that is reliable, then I think it could be put into Ext. Instead of subclassing, we could just do some extra preprocessing before the orignial constructor is called. I think that would be cool.