Writing a Big Application in Ext (Part 2)

2. February 2009 – 14:12

Important

If you have not already done so, study Writing a Big Application in Ext (Part 1) before you read this article. It would be very hard, if not impossible, to understand concepts explained here before you fully understand the first part.

Introduction

It has been almost one year since I have published the first part of this article. I have been successfully using the concept of pre-configured classes personally to write a really big application (~150 javascript files, ~60,000 lines of code, plus server-side and css). The application is fully modularized, each class in separate file and it has proven that it can be easily developed, managed and debugged.

Unfortunately, the same has not been always true for other users, they were hitting various problems and Ext Support Team have had to handle may questions and help requests. These accumulated to the degree where the concept has been called “absolute abomination” (read absolutely hated) and it was stated that “it causes problems”.

Note: As “fast cars” do not cause accidents but “slow drivers driving fast cars” do, the concept itself cannot be a cause of the problems but its application can.

In any case, there must be some illogic if I can use the concept but others cannot.

Thus, I have looked deeper in it and I have isolated some pitfalls the users can run into on the course of development. I will also write on “dos” and “don’ts” and on when to use a pre-configured class and when not. I will not compare this concept to another application design concepts (factory functions, in-line configuration, on-demand load, or other) because 1) I do not use them and 2) I do not want to turn this article into a Linux versus Windows discussion.

It is fully up to you which application design concept you choose. However, if you do choose this one then follow the rules I’m going to lay down.

Most Common Sources of Troubles

  • Dull Copy&Paste
  • Extending a non-Ext.Component class
  • Not calling parent methods
  • initialConfig
  • listeners

Dull Copy&Paste

Do you know such people? They post on a forum:

I need to drag from tree to qrid, gimme plz complete codez

And if somebody altruistic writes a fragment of “codez” for him in a sheer attempt to help the response is going to be:

Your codez don’t work. Help me plz my manager wants it working

Do you see what happened? A dull “developer” ordered a code on the forum, he’s got some, copied&pasted it to his application without a clue what the code does, maybe hasn’t even changed url that still points to your server and the result is: it doesn’t work.

Well, this is an extreme (but not so rare as you would think), nevertheless, copying&pasting without understanding of what the copied&pasted code does can lead only to frustrations.

I am not against Copy&Paste in general, it can save a lot of time and I also occasionally do it, but I am against not-understanding or mis-understanding not only of coding but also of life.

The Rule: Do Copy&Paste but always with full understanding of what the code does.

Extending a non-Ext.Component class

If an Ext class does not inherit from Ext.Component the initComponent is never called so the code you have written there is never executed. This is fragment from Ext.Component constructor:

1
2
3
4
5
6
7
8
9
    this.getId();
    Ext.ComponentMgr.register(this);
    Ext.Component.superclass.constructor.call(this);
 
    if(this.baseAction){
        this.baseAction.addComponent(this);
    }
 
    this.initComponent();

Ext classes that do not inherit from Ext.Component do not have this.initComponent(); line in their constructors.

The Rule: Always check if the Ext class you are going to pre-configure inherits from Ext.Component. You have to use an another approach if it does not.

Not calling parent methods

It happens very often that you do not only add some methods in your extended class but that you modify existing ones. initComponent being the first example. onRender, afterLayout are other (but not only) frequently overriden methods.

These methods are already implemented in the class you are extending and its parents so if you forget the line:

// in initComponent override
YourExtension.superclass.initComponent.apply(this, arguments);
 
// or in onRender override
YourExtension.superclass.onRender.apply(this, arguments);
 
// or in afterLayout override
YourExtension.superclass.afterLayout.apply(this, arguments);

your class will not work.

The Rule: Never forget to call the parent method, unless you exactly know what you are doing.

initialConfig

The constructor of Ext.Component saves the config passed to it as initialConfig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    /**
     * This Component's initial configuration specification. Read-only.
     * @type Object
     * @property initialConfig
     */
    this.initialConfig = config;
 
    Ext.apply(this, config);
    this.addEvents(/* abbreviated for clarity */);
    this.getId();
    Ext.ComponentMgr.register(this);
    Ext.Component.superclass.constructor.call(this);
 
    if(this.baseAction){
        this.baseAction.addComponent(this);
    }
 
    this.initComponent();

You see what happens? The constructor saves initialConfig before initComponent is executed. Thus, all configuration you write in initComponent is not saved. I have overlooked this in first versions of my templates and examples mainly because there is only a couple of classes that refer to initialConfig and even in these classes the absence of properly saved initialConfig causes problems very rarely. These Ext classes refer to initialConfig:

  • AnchorLayout
  • BorderLayout
  • Action
  • GridPanel
  • Tip
  • Combo
  • Form

Now, I have updated all my examples, extensions, templates and main site to include this “magic” pattern:

1
2
3
4
5
6
7
8
9
10
// create config
var config = {
    // put your config here
}; // eo config object
 
// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
 
// call parent
YourExtension.superclass.initComponent.apply(this, arguments);

The Rule: Ensure that your extension saves initialConfig.

listeners

If you try to install event handlers by setting property listeners in your config they will not work. Why? The answer lies again in the order of actions in Ext.Component constructor:

1
2
3
4
5
6
7
    Ext.Component.superclass.constructor.call(this);
 
    if(this.baseAction){
        this.baseAction.addComponent(this);
    }
 
    this.initComponent();

As you can see, the constructor calls its parent, that is Ext.util.Observable before initComponent. Ext.util.Observable constructor executes:

1
2
3
4
5
6
Ext.util.Observable = function(){
    if(this.listeners){
        this.on(this.listeners);
        delete this.listeners;
    }
};

Any listeners set in initComponent are thus ignored.

There is an easy workaround. Put constructor method in your extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
 constructor:function(config) {
    // parent constructor call pre-processing - configure listeners here
    config = config || {};
    config.listeners = config.listeners || {};
    Ext.applyIf(config.listeners, {
        // add listeners config here
    });
 
    // call parent constructor
    AnExtension.superclass.constructor.call(this, config);
 
    // parent constructor call post-processing
 
} // eo function constructor

and define your listeners therein.

The Rule: Define listeners in constructor method.

Conclusion

If you decide to use my way of writing a big application then follow these rules:

  1. Do Copy&Paste but always with full understanding of what the code does.
  2. Always check if the Ext class you are going to pre-configure inherits from Ext.Component. You have to use an another approach if it does not.
  3. Never forget to call the parent method, unless you exactly know what you are doing.
  4. Ensure that your extension saves initialConfig.
  5. Define listeners in constructor method.

Happy extending!

Do not forget to read Part 1 and Part 3 of this article.


StumbleUpon Toolbar
  1. 24 Responses to “Writing a Big Application in Ext (Part 2)”

  2. Thank you a lot, for sharing your experience with the community!

    Nice post.

    By Nils Dehl on Feb 2, 2009

  3. Thanks for writing this, it\’s great to see more ExtJS content around

    I think you\’ve got a couple of small bugs however:

    1) In your final code block, the constructor function won\’t always behave as you expect. It will only work correctly if the \’config\’ argument is passed, and is an object. If you call \

    By Ed Spencer on Feb 2, 2009

  4. Thanks for writing this, it’s great to see more ExtJS content around

    I think you’ve got a couple of small bugs however:

    1) In your final code block, the constructor function won’t always behave as you expect. It will only work correctly if the ‘config’ argument is passed, and is an object. If you call “new AnExtension()”, the config won’t be passed up the chain because there are no arguments. Better to write the super call like this:

    AnExtension.superclass.constructor.call(this, config);

    Your method of using apply is definitely the right one if you’re not modifying arguments though.

    2) line 3 of that same block needs to read “var config = config || {}”. Currently you’re declaring config as a global variable, which could cause hard to diagnose problems.

    Keep it up :)

    By Ed Spencer on Feb 2, 2009

  5. Thank you very much for the article. It helps a lot.

    If I may suggest the subject of next article, the third part of writing big application in Ext: it should focus on beforeDestroy and onDestroy methods.

    It happens from time to time, when one writes big application in Ext, that there is a need to destroy the component (or more generally the ext object). I would like to have a clean rule, what should I put to beforeDestroy method and why.

    This is what I miss a lot.

    Of course I can figure it out by myself, but my insight in Ext will, probably, never be as deep as yours.

    Thank you.

    By wregen on Feb 2, 2009

  6. 1. If config is passed and it is not object then you’re completely on another track as you would never override the constructor of a class if you’re not going to pass config object to it because primary reason of writing a constructor that way is to support listeners.

    You would choose another approach or you would write your own constructor or you would test for config type.

    Normaly, as an author of such class, I would document the constructor that the config must be object or nothing.

    If config is not passed it is not a problem, besides that it is programming error as config is not optional (if you don’t state otherwise), because new empty config is created by the following lines of the code.

    Also, call of parent is correct and it always gets config argument even if it was empty.

    2. IT MUST NOT read var config!!! config is delcared argument of the function and regardless if it was actually passed by the caller or not, it is NOT a global variable.

    By Saki on Feb 2, 2009

  7. Oh yes you\’re right about not needing the var – my mistake. Not sure where I picked that up from… You can still leave it in though, it just doesn\’t seem to do anything.

    However, I don\’t think that is correct about apply. I\’ve just put together a quick class which confirms what I said above – if the config argument is not passed then your code does not work, as it isn\’t in the arguments array. You\’re applying the properties to your config variable, which is a pointer to the first argument, but because the first argument isn\’t there it\’s not pointing at anything in the arguments object. Passing arguments up the chain just passes the empty arguments array – your applyIf block has no effect.

    If you try your code out you\’ll see this happening – calling the constructor without an argument will just ignore everything in applyIf. You could document it and force people to supply an empty object but surely it\’s easier to not take that risk and just make new AnExtension() equivalent to new AnExtension({})? The only change required is using call instead of apply. As you know the function signature anyway this is hardly a problem, and makes your code more flexible.

    By Ed Spencer on Feb 2, 2009

  8. Yes, you’re right – I’m changing it.

    By Saki on Feb 2, 2009

  9. Excellent! Now I can extend without people telling me to learn the \”implications\” first :-)

    By fREW on Feb 2, 2009

  10. @Saki cool :)

    I really like your stuff, we could do with another one or two of you ;)

    By Ed Spencer on Feb 2, 2009

  11. @Ed,

    Ext.ux.clone(Saki);

    ;)

    By Saki on Feb 2, 2009


  12. // in initComponent override
    YourExtension.superclass.initComponent.apply(this, arguments);

    I think You accidentally write ‘apply’ instead of ‘call’ in some examples.

    By madrabaz on Feb 3, 2009

  13. @madrabaz,

    no, that call is correct. initComponent is always called without arguments at present but if anything would change in the future apply(this, arguments) would handle it w/o any change in your extensions.

    Beware apply in the above call is not Ext.apply; they are completely different things.

    By Saki on Feb 3, 2009

  14. Hello! Nice article!

    > Do Copy&Paste but always with full understanding of what the code does.

    The first rule is nice goal, but not always realizable in real world. Sometimes you copy/paste a piece of code and if it works, you often can\’t spend time trying to understand, why it works.
    And when it doesn\’t work, you try to modify it, by comparing with the original, until it works… You often simply don\’t have the required time to completely understand how it works :) But it\’s really a nice objective.

    I copied few fragments of code from your examples. Some parts I understand, some not, but I don\’t bother, if they work ;)

    The software today is getting so complex, that you often just don\’t have the time to study it in such detail to thoroughly understand how it works. This trend will continue ;)

    By Robert on Feb 3, 2009

  15. @Robert,

    please read it again. I’ve written “what the code does”, not how does it do it.

    And, sorry for being harsh, if a developer is not able to deal with complexity of contemporary software, if he is not able or willing to understand his own job, then it would be better if he found another job.

    By Saki on Feb 3, 2009

  16. Just wanted to say that I\’ve followed the part one of this article for developing a very big extjs front-end (60k~ lines of javascript) and I wouldn\’t have been able to organize the code so well without your suggestions.

    I\’ll definitely follow the rules on this second part, and look forward for the third!!! ;)

    By Franjanko on Feb 3, 2009

  17. Thank you for the great article!

    By Sey on Feb 4, 2009

  18. Saki, I want to share my experience here.

    Initially, I\’m a Flex developer, but Big Client came to our company asking for ExtJS expert for developing Outlook+Gmail+IM alternative to be used in their intranet as info sharing application.

    We agreed, I\’ve heard about ExtJS and even run a couple of samples year ago.

    And then project started, I was very quickly learning ExtJS and was shooting my legs again and again, because all the JavaScript and JSON are so hacky for the ActionScript3 developer, who have compiler for all error checking, strict typing, and all static language comfort.

    Important moment, we use SCRUM for the development, and very tight deadlines.

    And then I\’ve discovered your patterns and learned a lot in one moment. I can\’t say it prevented me from making new errors, but your approach cleared a lot of questions, so now 2 months of development are gone, and I can say application is more or less stable, could be extended and supported further.

    I want to thank you for the great work you\’ve done, and all the inspiration of your samples.

    Regarding pitfalls, yes, I had it once, the one with listeners, which lead me to setting listeners in “onShow” method, but then I looked into your greatly documented code again and found my mistake.

    Thank you!

    By Rostislav Siryk on Feb 4, 2009

  19. @Rostislav,

    thank you very much for sharing your practical life experiences with extended classes here. I wish you good luck with them in the future.

    By Saki on Feb 4, 2009

  20. Saki: Thanks very much for these clarifications. We\\\’re working on a medium-sized ExtJS application (~14K lines right now, about 1/2 done), and are using pre-configured classes extensively. They\\\’ve worked very well for us.

    By Bill Hutten on Feb 25, 2009

  21. Thanks for this Saki. I am a complete convert to xtype and lazy instantiation. It makes my code more readable and easier to configure.

    By Relexx on Mar 13, 2009

  22. Hey Saki, thanks for this great article. It really got me going on extending Ext’s classes.

    I just wanted to give an update about the last section in this post about listeners. As of (I believe) Ext 3.2.0, you can now add a listeners property inside of initComponent(). This is due to Component.initComponent() duplicating Observable’s constructor for this very purpose (probably from so many people writing their own pre-configured classes!)

    By Gjslick on Aug 22, 2010

  23. Thanks, I’ll take a look and update the post if it really works in 3.2.x

    By Saki on Aug 23, 2010

  24. Hi. Nice work, that helpme much.

    So, I have a question.

    How can I call a parent listener (like keypress) when that listener has be overwritten?

    Thanks.

    By yyeshua on Apr 7, 2011

  25. It’s amazing to visit this web site and reading the views of all
    colleagues regarding this post, while I am also keen of getting
    familiarity.

    By blogwaldem.pinger.pl on Mar 1, 2014

Post a Comment