Page 1 of 4 123 ... LastLast
Results 1 to 10 of 31

Thread: code structure

  1. #1
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    8
      0  

    Default code structure

    Tutorials on extending, code structure, etc. in the wiki are getting a bit overpopulated and confusing people so I wanted to see if I could clean it up a bit. This thread is the working ground towards that end (entering / formatting text in the forums is much easier than the wiki).

  2. #2
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,890
    Vote Rating
    89
      0  

    Default

    I just wrote a detailed document for a client about why to extend Ext classes, which is the correct one to extend (eg, not Panel all the time), and how to extend.

    Since it was on chargeable time, I will ask them if they are willing to have it converted into HTML form and posted as a public tutorial. You'll understand if they want to keep it in-house...

  3. #3
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    8
      0  

    Default

    Application Design and Structure

    Simple

    In several of the examples the code is simply wrapped inside an Ext.onReady() block and may look something like this:

    Code:
    Ext.onReady(function(){
        // some code here
    });
    The examples are not suggesting that this is the best way to structure your code. This example is simply one way to keep the code compact and controlled.

    • Stuffing the code inside an Ext.onReady() block assures us that the DOM is ready prior to the code executing. Any code that works with the DOM will need the DOM ready to work with.
    • By wrapping the code inside a function, we've contained any properties properly defined with a var statement to be contained within the scope of this function instead of potentially conflicting with other variables in the global namespace.


    It is commonly preferred to manage your properties in some fashion so they do not conflict with other properties. In order to keep some control over the properties the browser is tracking you can utilize these techniques:

    1. closures,
    2. namespaces
    3. object oriented design.


    Closures

    An example of closures being used in practice can be found throughout the ExtJS library and also here. Closures provide a way to encapsulate properties that are only available internally, that is they are kept private. In the linked article and the example below, a function returns public or privileged properties which can be accessed or referred to externally; anything else is private because of "closure". Test the following in firebug:
    Code:
    var bubbly = function () {
    
        var foo = 1;  // private through closure
    
        return {
    
            public1: 3,
            privileged1: foo, // privileged can refer to private
            privileged2: function(){
                var ans;
                ans = foo;
                return ans;
            },
            privileged3: function(){
                var ans;
                // refer to other public properties with 'this'
                ans = foo + this.public1;
                return ans;
            }
        }
    }();  // parens immediately evaluates the function and 
          // assigns the returned result to variable 'bubbly'
    
    bubbly.public1;       // 3
    bubbly.privileged1;   // 1
    bubbly.foo;           // undefined
    bubbly.privileged2(); // 1
    bubbly.privileged3(); // 4
    Object Oriented design

    When you are thinking about creating reusable code using object oriented design principles you should consider the ramifications of the design pattern you intend to use.

    As with any software design pattern, each one has an appropriate situation in which they can work more effectively. If you look through the source code of ExtJS you'll see that ExtJS utlizes several design patterns, each is used for an appropriate interface.

    Two of the most common "patterns" (I used that term loosely here) used by end users of ExtJS are Factory and Extending. One pattern you will often see thrown around in the land of Ext is to use "preconfigured classes". Before blindly copying some code, you should understand the implications of using a particular design pattern without just blindly copying code. Some of the important questions you should know the answers for if you're choosing between Factory or Extending are:

    1. Should I really be extending in the first place, or creating a factory?
    2. If extending, what parts of my code need to be applied at the constructor level?
    3. If extending, what parts of my code can be applied at the initComponent level?



    Factory or Extend?

    If you are not changing or adding some value to a Class you may not want to Extend. If, for example, you have a set of panels that you know will have the same width and height, only the title is different. Other than that, you plan to use the original Class without alteration. In this situation, the only thing you are doing is configuring. Extending simply to configure is not required, instead you can use a Factory.

    If you choose to Extend please note some of the common pitfalls to be aware of:
    1. Applying properties to the prototype. Take care not to apply properties to the prototype Class that should only be applied to one object instance. The object that is passed to extend contains a set of properties which are going to be shared among all instances through a prototype property which every instance holds an implicit reference to.
    2. Taking all properties that you had in your configurable object and blindly stuffing it inside initComponent. Some properties need careful handling to work properly.


    Factory Pattern

    When we utilize the Factory design pattern it returns a new instance (object) of the Class. The Factory pattern is an alternative that is useful when the only thing you are doing is configuring, not extending/overriding the base Class behavior. An example:

    Code:
    function createMyPanel(config) {
        return new Ext.Panel(Ext.apply({//Pre-configured config options go here
            width: 300,
            height: 300
        }, config));
    };
    
    var myfirstpanel = createMyPanel({
        title: 'My First Panel'
    });
    
    var mysecondpanel = createMyPanel({
        title: 'My Second Panel'
    });
    See Saki's take on it here: http://blog.extjs.eu/know-how/factor...-file-pattern/

    Extending

    If you are adding or changing the behavior of the original base Class, extending is likely appropriate for your situation. If you are not altering the behavior of a class you should strongly consider using a Factory.

    ExtJs provides an utility function called Ext.extend(). Ext.extend() provides the mechanism for simulating class inheritance. This gives you the ability to modify or extend the base functionality of any JavaScript class without making code changes directly to the class itself (this is also commonly referred to as subclassing, or inheriting from, a base class). An example of using Ext.extend() follows:

    Code:
    // Extend the base class: (MyPanel Extends Ext.Panel)
    // The first argument to extend is the Class to be extended, the second argument is an object literal that
    // contains the properties to assign to all instances of the Class.
    
    var MyPanel = Ext.extend(Ext.Panel, {
    
        // Here you can add static variables for the class. Properties defined here
        // will be applied to the prototype for this base class, that is ALL instances
        // of this Class will then have these values (unless superseded by the constructors
        // config object).
        somePrototypeProperty: 'foo',
    
        // constructor function bundled within the extend method call:
        constructor: function (config) {
        
            // apply anything specified in the configuration object to this object
            Ext.apply(this, config);
    
            // Reusable config options here
            Ext.apply(this, {
                width: 300,
                height: 300
            });
    
            // call the superclass to preserve base class functionality
            MyPanel.superclass.constructor.call(this);
    
            // After call to superclass constructor has returned, our object (instance)
            // exists and the initComponent method has already been executed.
            // Here you can add functionality that requires the object to exist, 
            // like event handling for example. 
            this.on('resize', function(panel, w, h) {
                alert('Panel resized to ' + w + 'x' + h);
            });
        },
        
        // New function added
        myNewFunction: function() {
    
        },
    
        // Override an existing function
        onRender: function() {
            // when implementing a method from the base class, do not forget to
            // call the base class and pass this to ensure it runs in our object context.
            MyPanel.superclass.onRender.apply(this, arguments);
            this.myNewFunction();
        }
    });
    Notes:
    • JavaScript does not provide a mechanism for automatic invocation of superclass constructors, so you must explicitly call the superclass from the baseclass using the "superclass" property. The first argument for call() or apply() should always be ''this'' to ensure the execution context is the scope of the calling function.
    • A word of caution: The last argument for Ext.extend() is an object (an object literal) that holds the extended properties which are new/additional or replacement properties which will be copied into the subclass's prototype, and will therefore be shared between all instances of this new class. Properties that should not be applied to all instances of this class should not be specified here.
    • Note the usage of Ext.apply() (or Ext.applyIf) which is basically a convenience function to allow you to assign chunks of properties to an object (in this case "this") in one shot.
    • If you wanted to alter the behavior of an existing Class in place, you would use Ext.override() instead of Ext.extend(). For example if you want to override the behavior for one of ExtJS's core classes globally for your application you'd use Ext.override(). Common practice is to put overrides to the base library in separate file(s) and include them immediately after including the base library and just before your application specific code so your code implements from the altered state. Including overrides in separate file(s) instead of altering the original core code makes upgrades to new versions of ExtJS easier since your code is kept separate.


    To create instances of the custom Subclasses we would do:
    Code:
    var myfirstpanel = new MyPanel({
        title: 'My First Panel'
    });
    
    var mysecondpanel = new MyPanel({
        title: 'My Second Panel'
    });

    Template Methods

    The previous section illustrated the basic code to extend a Class. If your Subclass will inherit from the Component Class ExtJS implements a template method pattern so that we can more easily redefine certain steps of ExtJS's Component Class life cycle by overriding or contributing functionality at the key phases of a class's lifecycle.

    The most common template method to implement in your base Class is initComponent. initComponent is the first method executed after the constructor function is called and after the Component Class does some initial setup (more mentioned later about this initial set up).

    Code:
    // Extend the base class: (MyPanel Extends Ext.Panel)
    var MyPanel = Ext.extend(Ext.Panel, {
    
        // constructor function:
    //    constructor: function (config) {
    //        MyPanel.superclass.constructor.call(this, config);
    //    },
        
        initComponent: function () {
            // call the superclass to preserve base class functionality
            MyPanel.superclass.initComponent.apply(this, arguments);
        },
    
        // ...
    });
    Notice in the above snippet that manually implementing the constructor function is not required. As eluded to earlier, there are exceptions to this guideline though, because the Component Class does some initial setup before getting to the point where initComponent is called. During that initial setup, Component does things like get or generate an id, add any listeners in the config object, and create the objects initialConfig property. Some Classes require properties to be assigned to the initialConfig property in order to work properly (more on this to follow).

    So there are three options to consider when you need logic injected prior to the call to initComponent of your base Class:

    1. specify the properties in the configuration object
    2. inject the properties in the constructor function
    3. explicitly apply configs to this.initialConfig (illustrated in the code template below).


    Events

    ExtJS implements an observer pattern. In your extended class you may choose to subscribe to existing events or create new custom events.

    Subscribing to Existing Events

    To subscribe to existing events you have two options:
    1. specify a listeners property in configuration object for a new object (instance)
    2. use the on() or addListeners() method to add listeners to your instance in either the initComponent method or the constructor function. You want to add a listener prior to any chance of the event being fired otherwise the event will not be observed.


    Code:
    var MyPanel = Ext.extend(Ext.Panel, {
    
        // constructor function:
        constructor: function (config) {
            
            // apply anything specified in the configuration object to this object
            Ext.apply(this, config);
        
            // to add events at this point you use on() or addListeners()
            this.on('resize', function(panel, w, h) {
                alert('Panel resized to ' + w + 'x' + h);
            });
    
            // call the superclass to preserve base class functionality
            MyPanel.superclass.constructor.call(this);
        },
        
        initComponent: function () {
    
            // call the superclass to preserve base class functionality
            MyPanel.superclass.initComponent.apply(this, arguments);
    
            // to add events at this point you use on() or addListeners()
            this.on('resize', function(panel, w, h) {
                alert('Panel resized to ' + w + 'x' + h);
            });
        },
    
        // ...
    });
    Creating new Custom Events
    There are two parts to creating custom events.
    1. add (register) the custom event
    2. fire the custom event


    Add custom events in the initComponent method and fire custom events whenever it is appropriate for your event to be observed:

    Code:
    var MyPanel = Ext.extend(Ext.Panel, {
    
        // constructor function:
        constructor: function (config) {
            
            // apply anything specified in the configuration object to this object
            Ext.apply(this, config);
        
            // for classes not based on Component Class add custom events
            // in the constructor function before the call to the parent
            this.addEvents('assigned', 'dismissed');
    
            // call the superclass to preserve base class functionality
            MyPanel.superclass.constructor.call(this);
        
            // after the superclass has been called, subscribe to events
            // using on() or addListeners()
            this.on('resize', function(panel, w, h) {
                alert('Panel resized to ' + w + 'x' + h);
            });
        },
        
        initComponent: function () {
    
            // call the superclass to preserve base class functionality
            MyPanel.superclass.initComponent.apply(this, arguments);
    
            // for classes based on Component Class add custom events
            // in the initComponent function after the call to the parent
            this.addEvents('assigned', 'dismissed');
            
            // subscribe to events using on() or addListeners()
            this.on('resize', function(panel, w, h) {
                alert('Panel resized to ' + w + 'x' + h);
            });
        },
    
        assign:function(employee, position) {
            // do whatever is necessary to assign the employee to position
     
            // fire assigned event, specify parameters to be passed to the subscribers
            this.fireEvent('assigned', this, employee, position);
        },
     
        dismiss:function(empoyee, position) {
            // do whatever is necessary to dismiss employee from position
     
            // fire dismissed event
            this.fireEvent('dismissed', this, employee, position);
        }
    
        // ...
    });
    Events Summary
    • An Event is a message sent (fired) by an event source to inform listeners that something happened
    • An Event source is an object that can fire events
    • An Event listener is a function that is called when event source fires an event
    • To listen to existing events we use either the addListeners() or on() method to subscribe to an event on an Observable
    • To create a custom Event we implement the Observable class methods, addEvents and fireEvent
    • addListeners at the earliest point you can to make sure you catch all events that you're subscribing to. Adding a listener to something, assumes that something exists to attach the listener to. So the earliest you can add your listener is when that Observable exists.
    • Generally, you'll add listeners for observables your class is interested in inside the initComponent method (or the constructor function if you're not extending from Component).
    • Make sure the event you're attempting to subscribe to is actually implemented by that observable. For example, does a Ext.data.Store have a click event? No, so subscribing to the click event on a store instance will achieve no useful purpose.
      When we call fireEvent, Observable looks if there are any listeners for this event and calls for all listeners with the arguments we supplied in the fireEvent call. If there is no listener it will do nothing.



    Which Class should I extend?

    Here are some things to consider when you are trying to decide which class you should extend when subclassing. Basically, you should extend from the lowest class in the hierarchy which implements the functionality you need, so extending Ext.Panel is not always the best choice. A few notes follow, but a more thorough report is here:

    Extend from:
    • Ext.Component if:
      • all you need is some HTML element which encapsulates the thing you want to display,
      • and it doesn't need sizing by a layout.
      • Make sure you use autoEl to make it render something.
    • Ext.BoxComponent if:
      • you need something to participate in a sizing layout
      • Make sure you use autoEl to make it render something.
    • Ext.Container if:
      • you need something to contain other Components
      • Make sure you use autoEl to make it render something.
    • Ext.Panel if:
      • you just need the capabilities of Ext.Panel (header, footer, tbar, bbar etc)


    Scope
    In general you should have some basic understanding of scope, and when working with 'classes' this is no exception. Two common methods to ensure you are operating in the correct context:

    There are two tutorials that cover scope in the wiki:
    1. Introduction to Scope (global object, visibility, etc.)
    2. More about Scope (nested functions, scope config option, createDelegate)



    Extension Pattern Code Template

    The following code is a "skeleton" or outline of the template methods utilized by the Component class that you might use as a basis to form the code for your subclass. This template is specific to classes that extend Component, so if you are extending a class that is not a subclass of Component then the template shown here would need to be altered as some methods (like initComponent for example) are not called.

    PHP Code:
    /* "template" for extending */

    /**
     *
     * Ext.ux.Package.Class Extension Class
     * Extension of .....
     * @class Ext.ux.Package.Class
     * @extends Ext.grid.EditorGridPanel
     *
     * @author Your Name 
     * @version 
     * @date 
     *
     */

    /**
     * Ext creates a preconfigured user extension namespace (Ext.ux)
     * so we don't need to declare it again.  But, it would not hurt
     * anything if we did specify it again.  Namespaces are beneficial
     * so we don't have collisions with other variables and it helps to
     * organize our code better.
     */
    //Ext.namespace('Ext.ux');

    /**
     * Extend the base class
     *     MyExtendedClass = Ext.extend(SuperClass, {objectLiteral} );
     * The 1st argument is the name of the super / base class that will
     *    be extended (Ext.grid.EditorGridPanel)
     * The 2nd argument is an object (an object literal) that holds the extended
     *    properties which are new/additional or replacement properties which will
     *    be copied into the subclass's prototype, and will therefore be:
     *     >>> shared between all instances of this new class <<< .
     * So, Ext.extend takes the original class (the 1st argument) and
     *    optionally overrides members of it with the passed literal 
     *    (the 2nd argument) and returns our new extended class. 
     */

    Ext.ux.Package.Class = Ext.extend(Ext.grid.EditorGridPanel, {

        
    /**
        * @cfg {String} aClassProperty
        * Description for property.
        */
        
    aClassProperty'something'// ! Important : this property is applied to the prototype!
                                     // all instances of this Class will use this property
                                     // unless it is overriden when specifying the config
                                     // object for new instances:
                                     //   myNewObj = someClass({/* config here */})
        
        //end reconfigurables
        //-----------------------------------------------------------------------------

        /**
         * Anything that is wrapped within a function will not be assigned when
         * this subclass is created (before an instance is created).  Also note
         * that any references to 'this' placed outside of any class method (function)
         * will likely be the window object.
         */ 

        /** @private */
        
    constructor: function(config) { 
            
    //If you need configuration properties injected as a typical
            //configuration object would do you can specify them here
            //This can be used as a workaround to the initialConfig issues
            //mentioned elsewhere.

            // call the superclass's constructor 
            
    Ext.ux.Package.Class.superclass.constructor.call(thisconfig);
            
        }, 
    // eo function constructor 

        //-----------------------------------------------------------------------------
        //Begin template methods of Ext's Component Life Cycle

        /**
         * Ext follows a specified sequence when generating components (aka the
         * Component Life Cycle).  There are several "template methods" which provide
         * hooks at predetermined points during creation which we can inject the
         * appropriate code or behavior.
         */

        /**
         * initComponent
         * This is the most important initialization step for subclasses of the
         * Component Class (if you're not extending a decedent of Component this
         * method will not be called automatically).  This is a template method
         * intended to be implemented by each subclass to provide any needed 
         * constructor logic instead of using a separate constructor function.
         * initComponent calls the class being created first, and then each class
         * in the hierarchy back up to the Component Class using
         * superclass.initComponent. Using initComponent makes it easy to implement 
         * and, if needed, override the constructor logic at any step in the 
         * hierarchy. After each initComponent is executed for each parent all the 
         * way back up to Component then each parent class adds public events going
         * all the way back to our extended class / subclass. 
         */
        
    initComponent: function() { 

            
    /**
             * Anything inside functions (including this one) are not processed 
             * when this file is processed the first time.
             * We end up inside initComponent only after we create an instance
             * of this class. When we create an instance of a class we do something
             * like:
             *         var myEditorGrid = new Ext.ux.EditorGrid({config_properties});
             * So any configuration properties ('config_properties') specified in 
             * the configuration object of a new instance will be passed in here 
             * and be available as this.propertyName. 
             * 
             * Some caution is necessary when creating a subclass or making a 
             * preconfigured class in this way.
             * 
             * For some situations, Ext doesn't really anticipate this kind of 
             * configuration, specifically:
             *    BorderLayout (stated above)
             *    AnchorLayout (onLayout method)
             *    Tip (showAt method)
             *    ComboBox (queryDelay and minChars properties)
             *    FormPanel (possibly not, just deletes listeners)
             *    GridPanel (loadMask property)
             *    Component and Observable (cloneConfig method) 
             * If you look at Ext.Component's constructor (src/widgets/Component.js),
             * you will see that the initialConfig gets copied BEFORE calling 
             * initComponent. As a result anything you specify in initComponent will
             * not get copied to initialConfig (at least not without some special
             * manual help). initialConfig explicitly only copies the config 
             * object-literal that is specified as the constructor when calling:
             * new SomeClass({myConfigsHereThatWillGetCopiedTo_initialConfig})
             * 
             * So, again, any assignments made inside initComponent will override
             * any properties specified in the configuration object of an instance
             * (unless 'applyIf' is used in which case it won't overwrite them).
             */

            /**
             * ==BEFORE the call to the parent constructor==
             * Before the call to the parent constructor we typically are dealing
             * with CONFIGS in the this scope (the configs specified for a new 
             * instance of this class via new SomeClass{} are available at this point).  
             * Generally we apply things before the call to the parent constructor
             * for situations where you need to change/test/marshal configuration 
             * properties before the parent processes it.  
             * For example, you might test if a store has been passed in the config
             * for a grid, and if not, create a default store.
             * To specify or "apply" any configs we use this form:
             * Ext.apply(this, {objectLiteral})
             * Ext.apply( object, configObject, defaultsObject )
             *     object = The receiver of the properties
             *     configObject = The source of the properties
             *     defaultsObject = A different object that will also be applied for default values
             * 
             * In the line below, apply is a method of Function that calls the function
             * in the scope of the first argument, and accepts an array as the second
             * argument.  The array contains any arguments that we wish to pass.
             * As an example:
             *     function fn1 = function (a, b, c) {
             *         alert(a + b + c);
             *     }
             *     fn1.apply(this, [1, 2, 3]); //we can call above function this way
             */

            /**
             * default/alterable configurables
             * 
             * Specifying configurables here is useful for providing default values
             * for configuration parameters for example. We can still specify 
             * configuration options in the constructor for the new instance as well
             * since these configs will be copied into the new class using applyIf.
             * So any default properties specified here can/will be overridden if the
             * same properties are specified in the configuration object of a new instance.
             * 
             * The properties defined here will be available as:
             *    Ext.ux.ExtendedClassName.prototype.propertyName
             */
            //default/alterable configurables 
            
    var cfg = {
                
    //stuff to apply
                
    aReplaceableProperty1
            
    };
     
            
    //we use applyIf for configuration attributes that should be left configurable            
            
    Ext.applyIf(thiscfg);
            
    //ensure that any extra configurations that are set in initComponent method are
            //applied to initialConfig:
            
    Ext.applyIf(this.initialConfigcfg);

            
    /**
             * Properties specified here are safe/protected from being overridden
             * by an instance, so any 'private' default properties might be
             * specified here.
             */
            //some attributes we may want to keep unaltered, so we use Ext.apply
            //non-alterable configurables 
            
    cfg = {

            };

            
    Ext.apply(thiscfg);
            
    //need this to work sometimes:
            
    Ext.apply(this.initialConfigcfg);

            
    /**
             * Call parent initComponent (constructor)
             * This is a very critical step. By calling superclass.initComponent 
             * each parent class initiates a call to the constructor of it's 
             * parent class in succession all the way up to the Component Class
             * (see the API for the hierarchy of any class).
             * The form of this call is:
             *   MyExtendedClass.superclass.initComponent.apply(this, arguments);
             *   
             * While inside the initComponent method, arguments will contain an array
             * of arguments that the function received when called.  What we're doing
             * is that we pass these arguments without change to the parent call. By
             * passing 'arguments' we are being general in that 'arguments' can be
             * any number of elements, even empty.
             */

            // call parent 
            
    Ext.ux.Package.Class.superclass.initComponent.apply(thisarguments);

            
    /**
             * ==AFTER the call to the parent constructor==
             * The parent constructor instanciates components and puts them in 
             * MixedCollection, so the object is 'live' but is not rendered yet.  
             * At this point we typically are dealing with PROPERTIES in the this 
             * scope (all configs are available as this.whatever). After the parent
             * constructor we might apply additional properties before rendering 
             * (event handlers, etc.) that either extend or override the 
             * parent class behavior.  For example, at this point we can change 
             * this.title, but after the object is rendered we will need to use 
             * this.setTitle() (see the afterRender method below for example).
             */
            
    Ext.apply(this, {
                
    //stuff to apply (events, etc.)
            
    }); // end of apply

            //add custom events (you must 'fire' them later, this just adds/documents them)
            
    this.addEvents('assigned''dismissed');

            
    /**
             * Add any listeners
             * >>>Do NOT make a class property called listeners<<<
             * A listeners config option will have no effect at this stage!!! 
             * The listeners config option is read by a Component's superclass constructor,
             * the Ext.util.Observable constructor.
             */
            
    this.on({
                
    //listener configs
                
    renderthis.initializeSomething,
                
    afterlayoutthis.setSomething,
                
    scopethis
            
    });
        }, 
    // eo function initComponent 
        
        /**
         * After initComponent ext will:
         *     Check if any plugins have been specified in the config and call
         *         the init method of each plugin.
         *     Check if stateful == true and if so does initState
         *     Check if applyTo or renderTo are specified and executes the first
         *         of the two that is defined
         */
        
        /**
        * onRender is where you would add elements to the DOM element repesenting
        * a Component. After the call to the parent class returns, this.el is typically
        * available for you to use
        * @private
        */
        
    onRender: function (containerposition) {

            
    // before parent code

            /**
             * Call parent method
             * The pattern of calling the parent (superclass) method is always the
             * same.  We call the parent to ensure we start with the capabilities
             * of the parent class before we apply any additions or overrides.
             */
            //MyExtendedClass.superclass.onRender.apply(this, arguments);
            
    Ext.ux.Package.Class.superclass.onRender.apply(thisarguments);

            
    // after parent code
            // work with any code that requires this.el to exist

        
    }, // end of function onRender

        // template method
        /** @private */
        
    initEvents: function(){
            
    //call parent - be very careful to always call the parent, otherwise you may
            //break the component
            
    Ext.ux.Package.Class.superclass.initEvents.apply(thisarguments);

        }, 
    // end of function initEvents

        // template method
        /** @private */
        
    afterRender: function(){
            
    //call parent
            
    Ext.ux.Package.Class.superclass.afterRender.apply(thisarguments);

            
    //after rendering, we can set a value if defined in the config
            //if (this.value){
                //console.info('inside afterRender with this.value = ',this.value);
                //this.setValue(this.value);        
            //}
            
        
    }, // end of function afterRender

        // template method
        /** @private */
        
    beforeDestroy: function(){
            
    //call parent
            
    Ext.ux.Package.Class.superclass.beforeDestroy.apply(thisarguments);

        }, 
    // end of function beforeDestroy

        /**
        * onDestroy is called whenever an instance of a Component is destroyed.
        * You will want to implement this method if you have created resources
        * which Ext would not know about (context menu's and other items you
        * add which are not natively part of a class and so Ext would have no way
        * of knowing when or how to clear them up).
        * @private
        */
        
    onDestroy: function(){
            
    // call the superclass's onDestroy to get the usual cleanup done
            
    Ext.ux.Package.Class.superclass.onDestroy.apply(thisarguments);

            
    // perform your own custom cleanup logic (destroy cmenu's, etc.)
        
    }, // end of function onDestroy

        //End template methods of Ext's Component Life Cycle
        //-----------------------------------------------------------------------------
        //Begin new or replaced methods

        /**
         * Overrided/Extended methods
         * Anything that is wrapped within a function will not be assigned when
         * this subclass is created (before an instance is created).  Any 
         * references to 'this' will operate on this extended class object
         * (unless called with a specified scope using scope: or createDelegate).
         */ 
        
    aNewMethod: function() {
            
        }
        

    }); 
    // end of extend

    //================================================================

    /**
     * Register xtype 
     * We register new subclasses of Ext.Component so that lazy instantiation may 
     * be used when specifying child Components. For standard classes we would 
     * specify a valid xtype from Ext.Component (see API for options). For our
     * extended class we'll define our own unique xtype so we can then use the
     * extension simply by specifying the xtype in the config. 
     * We use the following format to associate the xtype with the Class:
     *     Ext.reg('my-component-xtype', MyExtendedClass);
     * see http://extjs.com/learn/Tutorial:Xtype_defined for more information.
     */
    //convention is to use all lowercase for xtype
    Ext.ComponentMgr.registerType('ux-package-class'Ext.ux.Package.Class);

    // end of file 
    Examples using the structure above:


    xTypes and initComponent

    An under the hood examination

    initialConfig

    See this thread for more discussion on issues with initialConfig to be aware of. Searching through the source there's at least these that are potentially affected, but there are more affected:
    • Tip (width)
    • BorderLayout (several properties for Region and SplitRegion
    • AnchorLayout (width and height)
    • GridPanel (loadMask)
    • BasicForm
    • Combo (queryDelay, minChars)
    • Component Cloning
    • Action (scope, iconCls, text)


    Developer Responsibilities
    A few notes on things to keep in mind when creating your own classes:
    • Destruction of custom attributes (context menus...)

  4. #4
    Sencha Premium Member
    Join Date
    Jul 2007
    Posts
    256
    Vote Rating
    1
      0  

    Default

    Nice Post!

  5. #5
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,890
    Vote Rating
    89
      0  

    Default

    Very good. This document I have done covers a lot of that.

    Perhaps if I get permission to use it you could help with converting the Word format to Wiki.

    One thing I did have was which class is appropriate to extend. People often extend Panel to do everything.

    If all you need is some HTML element which encapsulates the thing you want to display, and it doesn't need sizing by a layout, then extend Ext.Component. Ensuring you use autoEl to make it render something.

    If you need something to participate in a sizing layout, extend Ext.BoxComponent (using autoEl)

    If you need something to contain other Components, extend Ext.Container (using autoEl)

    It's only if you need the capabilities of Ext.Panel (header, footer, tbar, bbar etc) that you need to extend Ext.Panel.

  6. #6
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    8
      0  

    Default

    Anyone that wants to post or PM any content to me I'll try to massage into this to add to the wiki.

    I think I'll add a poll and ask people to bump this thread if they think I should remove the previous multitude of tutorials from the tutorials home page and replace it with just this one. I would link to those tutorials at the bottom of this one so they are not lost. Part of the motivation to pull this together has been the repeated popup of threads surrounding this matter.

  7. #7
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    8
      0  

    Default

    Eh. Looks like I can't change to add the poll. Just bump with any opinions/suggestions. I'm reluctant to move another author's work to less prominent exposure.

  8. #8
    Sencha User jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    DC Area =)
    Posts
    16,364
    Vote Rating
    86
      0  

    Default

    Quote Originally Posted by mjlecomte View Post
    Part of the motivation to pull this together has been the repeated popup of threads surrounding this matter.
    The repeated threads will continue despite your efforts, though they are very much appreciated dude.

  9. #9
    Sencha User jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    DC Area =)
    Posts
    16,364
    Vote Rating
    86
      0  

    Default

    Quote Originally Posted by Animal View Post

    If you need something to contain other Components, extend Ext.Container (using autoEl)
    You and I both use it, perhaps the online documentation should be updated?


    http://extjs.com/learn/Ext_2_Overview#Container_Model

    ...The Container class should never need to be used directly,....

  10. #10
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,890
    Vote Rating
    89
      0  

    Default

    The doc comments in the latest code in SVN do suggest using the lowest class in the hierarchy which implements the functionality you need, so yes, the overview needs to be updated to reflect this.

Page 1 of 4 123 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •