Migrating web applications from Ext JS 3.0 to 3.3

Ext JS is a good framework to build complex web UIs in JavaScript, because it provides many useful widgets. There’s always a dark side, anyway: in our case, when we started writing PhpReport 2.0, we had to rely on some undocumented features taken out from examples to get some things done.

Unfortunately, as new versions are released, some of these ‘features’ change their behaviour, or just disappear; maybe because they actually were side effects, or they were WIP. And moving to a newer version of the framework became an unexpected problem.

We started PhpReport 2.0 using Ext JS version 3.0, upgrading util 3.0.3. Then we found out that the jump to the next major version required more than downloading a new tgz, so we left it on hold, until some weeks ago, when I decided to get the latest Ext JS (3.3.1 right now) and put some effort debugging the problems caused by the migration. I share here with you the challenges I found.

XmlWriter and tpl attribute

This attribute is used to specify the conversion between the Store object with the data and the XML that has to be output, for example, to a REST service. To iterate over the fields of a record, we used this template: <tpl for="fields">. Now, that element isn’t called ‘fields’ anymore, and you should use <tpl for="."> to iterate over the fields of a record.

Null values on records

In Ext 3.0.3, Ext.data.Field objects didn’t have the useNull configuration option. It was introduced later, and its default value is false. This caused that some non compulsory fields stored a 0 when the user wanted them to be empty. The solution is simple: adding useNull: true to those fields when defining the corresponding Record.

Columns with empty ids on grids

When you used a empty string as the id of a column in 3.0.3, the grid showed a column with an empty label, and those records of the Store with an empty field name were rendered in that column. But that no longer works in 3.3.1, where every column has to have its id.

Changes in the behaviour of ref property

ref is a path specification, which allows us to place a named reference to a component in one of is owner containers. It seems there were some changes in the implementation of this attribute in Ext 3.1. Look at this example:

Ext.onReady(function(){
    var g = new Ext.grid.GridPanel({
        renderTo: document.body,
        store: [1],
        columns: [{
            header: 'col'
        }],
        tbar: new Ext.Toolbar({
            items:[{
                text: 'Foo',
                ref: '../deleteBtn'
            }]
        }),
    });

    new Ext.Button({
        text: 'Click',
        renderTo: document.body,
        handler: function(){
            console.log(g.deleteBtn);
        }
    });
});

It worked flawlessly in 3.0.3. When clicking on the button, the system writes g.deleteBtn in the JavaScript console. deleteBtn is not a direct child of g, but we achieved this direct access using ref.

After the migration, something ‘under the hood’ made this code broke, but taking a look at it, the only questionable thing is the definition of the toolbar, which can be simplified. After some experiments, I found out that the problem was fixed changing that definition:

        tbar: [{
            text: 'Foo',
            ref: '../deleteBtn'
        }]

Now ref works correctly again. Not sure about what happened, but it seems that the redundant definition of the toolbar now has this undesired side effect.

So…

It was an unexpected effort, but I’m happy with the results. I was waiting to get some annoying cross-browser bugs solved, for example, those huge calendars in WebKit-based browsers. I have the migrated code of PhpReport in a separate branch called migration-to-ext-3.3.1, and we are testing it heavily right now, before merging into master.