One of the principles of the object–oriented programming says that the functionality should be encapsulated into a component and handled by the component. It helps to keep the functionality in one place and modify it easily or rewrite/replace it completely without affecting other parts of an application.

Since ExtJS is an object–oriented JavaScript framework, the same principle should be used there.

Recently I had to create a numerous ExtJS components for one project. There are numerous ExtJS examples on the web, which show complex components but often they do not follow the encapsulation principle. I decided to make it the "right way" and I am going to show how.

ExtJS panels in action

ExtJS panels is the most generic way to display content in ExtJS. Panel can either show an HTML content or serve as a container for other items (such as grids, trees, charts, etc). Imagine you need to put a data view into the panel and next put the panel to a tab panel. This is how many example will suggest it to be:

var tabPanel = ...;
var panel = new Ext.Panel({
    ...
    items: new Ext.DataView({
        ...
        store: new Ext.data.JsonStore({
            ...
        }),
        tpl: new Ext.XTemplate(
            '<ul>',
                '<tpl for=".">',
                    '<li>{mydata}</li>',
                '</tpl>',
            '</ul>',
        ),
        ...
    }),
    ...
});
tabPanel.add(panel).show();

This works. However if you need to change the template or if the store has a lot of fields, the whole piece of code becomes huge and eventually unmaintaibable. It may spread over hundreds of lines.

How to make it better?

ExtJS panels as a custom component

The solution is to make a custom component from the ExtJS panel. For that we create a separate file (not a requirement but convenience) and place the following content there:

Ext.onReady(function() {
    Ext.namespace('example');

    example.MyComponent = Ext.extend(Ext.Panel, {
        // Put panel specific options here, for example:
        autoHeight: true,
        bodyBorder: false,
        collapsible: true,
        cls: 'my-component',
        collapsible: true
    });
});

That isolates component–specific options inside the component. However it lacks the DataView. The reason for it is simple. When overriding panels, you can't set items property of the panel. ExtJS will override it in the Panel constructor with a null value. On order to create items you have to override the initComponent method like this:

Ext.onReady(function() {
    Ext.namespace('example');

    example.MyComponent = Ext.extend(Ext.Panel, {
        // Put panel specific options here, for example:
        autoHeight: true,
        bodyBorder: false,
        collapsible: true,
        cls: 'my-component',
        collapsible: true,

        /**
         * Initializes the component.
         */
        initComponent: function() {
            this.items = new Ext.DataView({
                ...
            });
            example.MyComponent.superclass.initComponent.call(this, arguments);
        }
    });
});

Notice that we must call parent class method in order to initialize the panel.

Now we encapsulated all component–specific options inside the component. Later if we decided to change DataView to GridPanel, we can do it easily inside a separate file without worrying about side effects on the rest of the application.

This is a first of my articles about ExtJS. I work with ExtJS much more than with TYPO3 these days and for some time will focus on ExtJS programming. If anyone has questions about ExtJS, you are welcome to send them to me and I will try to cover them on the blog.