Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Ext - Inheritance Vs Encapsulation

  1. #1
    Ext User santosh.rajan's Avatar
    Join Date
    Sep 2007
    Location
    Kannur, Kerala, India
    Posts
    611

    Default Ext - Inheritance Vs Encapsulation

    I have seen in these forums that a lot of people are using inheritance (extend) to solve their problems. I for one have never found a reason to extend any Ext Class so far. This is because Ext is an amazingly comprehensive library.

    Inheritance is required only if you want to extend the existing functionality of an Ext component. Another option is to encapsulate Ext components within your Class.

    First of all you dont need to develop your Class unless you need a reusable object. I have seen here examples of Inheritance for Singletons. If you are going to use your object only once there is no need for creating any classes (inherited or encapsulated).

    When do you inherit and when do you encapsulate? You inherit when you want to add functionality to an existing component. You encapsulate when your object 'uses' components. You inherit if your new class "is a" Ext Component. You encapsulate if your new class "has a" Ext Component.

    Here I am going to give you an example of encapsulation. I needed a simple reusable Desktop Icon Class. I needed an icon and some text below it when clicked does some action.(just like your desktop icons). So i created this class which requires as input an icon(path to the image), some text to show below image, a function to call when clicked, and the scope for the function. Also the icons have to be transparent. Here is the code.
    Code:
    Ext.namespace('MYOFIZ');
    MYOFIZ.DeskIcon = function() {
        // Private function
        function setCmp(config) {
            return new Ext.Panel({
                border: false,
                bodyStyle: 'margin: 15px; text-align: center; vertical-align: top; cursor: pointer; background: transparent; font-size: 12px;',        
                listeners: {
                    'render': function(panel) {
                        panel.getEl().on({
                            'click': config.openFn.createDelegate(config.scope)
                        })
                    }
                },
                items: [{
                    xtype: 'panel',
                    border: false,
                    width: 100,
                    bodyStyle: 'background: transparent;',        
                    html: '<img src="' + config.iconpath + '"/>'
                },{
                    xtype: 'panel',
                    border: false,
                    width: 100,
                    bodyStyle: 'background: transparent;',        
                    html: config.text
                }]
            });
        };
        //////     return Class constructor
        return function(config) {
            this.extCmp = setCmp(config);   // Create Ext Component here
            this.render = function(el) {this.extCmp.render(el);}; // Called by Parent Container
            this.destroy = function() {this.extCmp.destroy();}; // Called by Parent Container
        };
    }();
    
    ///////////// Usage
    
        var panel = new Ext.Panel({
            layout: 'table',
            layoutConfig: {columns: 6}
        });
    
        var icon = new MYOFIZ.DeskIcon({
            iconpath: "images/upload64.png",
            text: "Upload File",
            openFn: this.uploadHandler,
            scope: this
        });
        panel.add(icon);
    The constructor creates an ext component. (this.extCmp). setCmp is a private function that simply returns a new icon based on the config options.

    I have implemented render and destroy functions so that i can add this object to a Ext Container. Your Ext Container will call these functions. If you dont want to implement render and destroy then you will have to do
    panel.add(icon.extCmp);

    In this case the icon can be any size but it should be a transparent image. Here i have limited the width to 100. Smaller images will be centered. When the mouse hovers over the icon it is changed to a pointer(hand).

    This is a simple case of encapsulation. You can create more complicated objects with multiple components, and many private and public functions.

    I have attached a screenshot below of multiple icons created and rendered in a tabpanel with table layout.
    Attached Images Attached Images

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

    Default

    Yes, I think the only time you need to extend a class is if you need access to all the methods of the class, plus more, or you need those same methods to do more (ie your subclass implements those methods, and calls the superclass methods).

    If you need an abstraction of say a FormPanel which performs some application-specific operations that you define, then write a class which has a FormPanel.

    As for the above code, I have discussed that pattern in another thread. It offers privacy at the cost of memory footprint. I would code it like this:

    Code:
    Ext.namespace('MYOFIZ');
    MYOFIZ.DeskIcon = function(config) {
        this.initialConfig = Ext.apply(config, {
            border: false,
            bodyStyle: 'margin: 15px; text-align: center; vertical-align: top; cursor: pointer; background: transparent; font-size: 12px;',        
            listeners: {
                'render': function(panel) {
                    panel.getEl().on({
                        'click': config.openFn.createDelegate(config.scope)
                    })
                }
            },
            items: [{
                xtype: 'panel',
                border: false,
                width: 100,
                bodyStyle: 'background: transparent;',        
                html: '<img src="' + config.iconpath + '"/>'
            },{
                xtype: 'panel',
                border: false,
                width: 100,
                bodyStyle: 'background: transparent;',        
                html: config.text
            }]
        });
        this.panel = new Ext.Panel(this.initialConfig);
    };
    
    MYOFIZ.DeskIcon.prototype = {
            myApplicationSpecificFunction: function(p1, p2, p3 {
                // Perform application-specific processing
            },
    
    //     Make this class usable by a Container, so that we can add and remove it.
    //     Create delegates in the scope of our contained Panel which reference Panel's methods
            render: Ext.Panel.prototype.render.createDelegate(this.panel),
            destroy: Ext.Panel.prototype.destroy.createDelegate(this.panel)
        };
    };

  3. #3
    Ext User santosh.rajan's Avatar
    Join Date
    Sep 2007
    Location
    Kannur, Kerala, India
    Posts
    611

    Default

    Thanks Animal for pointing out the memory footprint implications and code.

  4. #4
    Sencha User
    Join Date
    Mar 2007
    Location
    Bah
    Posts
    434

    Default

    FYI, this is the other thread Animal was talking about:

    Help: How render multiple FormPanel instances via a parent Panel.items config

    I appreciate this kind of discussions, and wish they were more frequent and/or detailed. I was happy because I began extending Ext classes for the first time a few days ago, and now you show me that perhaps what I really needed was encapsulation... (mine is more a "has a" than a "is a" situation)

    Not sure if it's easy to decide which approach to take --how much can that memory footprint impact be?--, but anyway it's good to learn about the different patterns available.

    EDIT: I had read without understanding... the memory footprint problem is associated with the original code, but not with Animal's. I'll try to implement this in my application now. Thanks!
    Fernando G

  5. #5
    Sencha User
    Join Date
    Mar 2007
    Location
    Bah
    Posts
    434

    Default

    This has the potential for a good wiki page. I've started one here:

    http://extjs.com/learn/User:Efege:Encapsulation_in_Ext

    It's just a first step, it could even evolve into a tutorial...

    Please feel free to improve.
    Fernando G

  6. #6
    Sencha Premium Member
    Join Date
    Jul 2007
    Posts
    256

    Default

    I'm a newbie, so sorry for the simple question; In this example, you are creating a panel for the icon and a panel for the text right? I was under the impression that panels were a box with a header that content would go inside. But if I read this right, does this mean the 'panel' is the basic building block for any element that you want to be able to render?

    Sorry if this is dumb question, the use of panel just threw me...

  7. #7
    Ext User santosh.rajan's Avatar
    Join Date
    Sep 2007
    Location
    Kannur, Kerala, India
    Posts
    611

    Default

    You are right i could have put both the image and text in one panel. But this was a conscious design decesion of mine bcos in future if i wanted to make the text editable for example, having it in two panels inside is better.

  8. #8
    Ext User santosh.rajan's Avatar
    Join Date
    Sep 2007
    Location
    Kannur, Kerala, India
    Posts
    611

    Default

    After working on this approach the last few days i have now come to the conclution an even simpler approach would be the best considering all the factors discussed above.
    Here is the new code
    Code:
    MYOFIZ.DeskIcon = function(config) {
        this.panel = new Ext.Panel({
            border: false,
            bodyStyle: 'margin: 15px; text-align: center; vertical-align: top; cursor: pointer; background: transparent; font-size: 12px;',        
            listeners: {
                'render': function(panel) {
                    panel.getEl().on({
                        'click': config.openFn.createDelegate(config.scope)
                    })
                }
            },
            items: [{
                xtype: 'panel',
                border: false,
                width: 100,
                bodyStyle: 'background: transparent;',        
                html: '<img src="' + config.iconpath + '"/>'
            },{
                xtype: 'panel',
                border: false,
                width: 100,
                bodyStyle: 'background: transparent;',        
                html: config.text
            }]
        });
    };
    
    MYOFIZ.DeskIcon.prototype = {
        getExtComponent: function() {return this.panel}
        // Your other class specific functions here
    
    };
    You will notice that i have done away with initialConfig and the render and destroy. Instead i have a function that returns the Ext component. So to add this instance object you have to do
    container.add(obj.getExtComponent()).
    The reason i have done this is so that Ext can then do whatever it does in the way the ext designers have exposed the interface. In the earlier approach you needed a deeper understanding of Ext (to a level not exposed in the interface).

  9. #9
    Sencha User
    Join Date
    Mar 2007
    Location
    Bah
    Posts
    434

    Default

    brookd, you are not asking a dumb question.

    It's true that Panel sometimes offers too much (I quote the API docs):

    The Panel contains bottom and top toolbars, along with separate header, footer and body sections. It also provides built-in expandable and collapsible behavior, along with...
    But both header and footer are optional (boolean config properties), so you can see a Panel as a single box -- its body. And it's easy to specify its content using the html config property.

    On the other hand, you can also use other simpler component types ('container', 'box', event 'component' itself), and with the applyTo config it's possible to use existing HTML as the component's content... but I haven't explored this yet.
    Fernando G

  10. #10

    Default

    When developping a component using encapsulation, I wonder when to use the pattern described above and when to use
    the module pattern described at http://extjs.com/learn/Manual:Basic_Application_Design?
    Thank you for your help

Page 1 of 2 12 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
  •