Writing Ext JS Overrides

Armando Gonzalez

July 11, 2014

Sencha Frameworks are well known because of their architecture, the way its classes are organized and structured. This is part of what makes it a leading framework in cross browser and cross platform development. When developing robust applications a good software architecture is a must have. It will guarantee an easy development process, better deployment cycles, and short, efficient refactoring phases (not to mention faster bug fixes.)

When using a framework, I sometimes find a bug, or a certain behavior that I would like to change. Though there are multiple ways to solve this kind of issue, such as extending that class and using that extension in lieu of a base framework class, sometimes the only option is to override a method for a base class.

Say, for example, I need to change the behavior of Ext.container.Container. This base class is a superclass for so many UI widgets in the framework. Below is a snippet of the inheritance model for Container.

Screenshot 2014-06-26 15.33.13

Ext.override is mainly used for fixing bugs or changing the core behaviors of certain classes. In this post you will see a prime example of how to use Ext.override in applications.

A real world example

Imagine for a moment using a vanilla Ext JS data Store that is filtered via some query. Even if a filter has been applied, there is still a requirement needed to remove all records from that store. So, when I execute store.removeAll I expect all records to be removed from the data Store. But, this is not what happens. When a store is filtered, a call to removeAll simply removes all filtered records, not all records.

So, to accomplish that task I am going to override the removeAll method for all the stores in my project.

Overriding methods

note: This process should work as if you are using the new version of the framework ExtJS 5. Sencha has designed a standard architecture to solve this kind of issue, placing an override folder in their project structure.

Creating my ExtJS 4 project using Sencha CMD

manduks$ sencha -sdk /path/to/ext-4.2.2 generate app OverridesInExtJS ../OverridesInExtJS

Now I am going to add the model, store, and grid to show my information. (The complete code can be found here) https://github.com/manduks/OverridesInExtJS

Model definition.

Ext.define('OverridesInExtJS.model.User', {
    extend: 'Ext.data.Model',

    fields:[
        {
            name : 'id',
            type : 'int'
        },
        {
            name : 'name'
        },
        {
            name : 'twitter'
        }
    ]
});

//Store definition.
Ext.define('OverridesInExtJS.store.Users', {
    extend   : 'Ext.data.Store',
    requires : [
        'OverridesInExtJS.model.User'
    ],

    model    :'OverridesInExtJS.model.User',
    autoLoad : true,

    data : [
        {id : 1, name : 'Patrick Sheridan', twitter : ' @sheridap'},
        //…
        {id : 30, name : 'Timothy Eagan', twitter : '@TimothyEagan'},
        {id : 31, name : 'Tyler Knappe', twitter : '@tknappe'}
    ]
});

Grid definition

Ext.define('OverridesInExtJS.view.users.UsersGrid', {
    extend : 'Ext.grid.Panel',
    xtype  : 'usersgrid',
 
    title   : 'Users',
    store   : 'Users',
    columns : [
        {
            text      : 'ID',
            dataIndex : 'id'
        }, 
        {
            header    : 'NAME',
            flex      : 3,
            dataIndex : 'name'
        }, 
        {
            header    : 'TWITTER',
            flex      : 2,
            dataIndex : 'twitter'
        }
    ],
    tbar : [
        '->',
        {
            text   : 'Filter',
            itemId : 'filter'
        },{
            text   : 'Clear Filter',
            itemId : 'clearFilter'
        },{
            text   : 'Remove All',
            itemId : 'removeAll'
        }
    ]
});

Main controller definition.

Ext.define('OverridesInExtJS.controller.Main', {
    extend : 'Ext.app.Controller',
    refs   : [{
        ref      : 'usersGrid',
        selector : 'usersgrid'
    }],

    init : function() {
        var me = this;
        me.control({
            'usersgrid #filter': {
                click : me.onFilterGrid
            },
            'usersgrid #clearFilter': {
                click : me.onClearFilter
            },
            'usersgrid #removeAll': {
                click : me.onRemoveAllUsers
            }
        })
    },
    onFilterGrid : function(btn) {
        Ext.getStore('Users').filterBy(function(record) {
            return record.get('id') > 10;
        });
    },
    onClearFilter : function() {
        Ext.getStore('Users').clearFilter();
    },
    onRemoveAllUsers : function() {
        Ext.getStore('Users').removeAll();
    }
});

Once I have my grid ready and added to the main view I will have something that looks like this:

Screenshot 2014-06-26 16.19.33

This is the store behavior:

  1. First I filter my data by clicking the “Filter” button, which will then display all the records where id is greater than 10.

  2. Then, I will remove all the records from the store by clicking the “Remove All” button.

  3. After that, I will clear the store filter by clicking the “Clear Filter” button and I am left with only records where id is less than or equal to 10.

This process is shown in the following image.

1

Notice the store.removeAll method of the store is not removing the unfiltered records. The complete code to this step is here.

Now I am going to make some changes to the removeAll method of my Ext.data.Store; For that I am going to use the Ext.override method. First, I need to see where the overrides go. If I navigate through my project I will find that Sencha Cmd has already created a folder where our overrides of the framework.

Screenshot 2014-06-26 16.20.28

Now I will add the store override. Using the convention of how Sencha has its own class files, I need to create a data folder inside my overrides folder. It is in this folder that I will place our Store.js class file.

Screenshot 2014-06-26 16.21.15

To override my store I just need to call the clearFilter method before the rest of the removeAll method logic happens.

/**
 * @class Ext.data.Store
 * @overrides Ext.data.Store
 * This is the code for overriding the store`s removeAll method
 */
Ext.define('Ext.data.Store', {
    override :'Ext.data.Store',

    removeAll : function () { 
        this.clearFilter(); //clear any filters than remove
        this.callParent(arguments);
    }
});

Now I need to include my overrides. For that I am going to add the path where the project can use the overrides to the beginning of my app.js file and require my overrides there.

/*
    This file is generated and updated by Sencha Cmd. You can edit this file as
    needed for your application, but these edits will have to be merged by
    Sencha Cmd when upgrading.
*/

Ext.Loader.setConfig({
    paths : {        
        'Overrides': 'overrides'
    }
});

Ext.application({
    name   : 'OverridesInExtJS',
    extend : 'OverridesInExtJS.Application',

    requires : ['Overrides.data.Store'],// importing our overrides

    autoCreateViewport : true
});

Once I have added the overrides to my code, I am ready to test my application and check if the store is removing all the records and not only the filtered ones.

2

The image above shows that the override works like a charm! To ensure that my overrides are included in my testing and production builds, I’m going to need to modify a Sencha Cmd configuration file. Here’s my updated .sencha/app/sencha.cfg file.

# The path(s) to application javascript sources (comma separated)
app.classpath=${app.dir}/app,${app.dir}/app.js,${app.dir}/overrides

Now I’m ready to generate a testing or production build

Conclusion

In this post, I reviewed how to override core functionality of the framework using the Sencha conventions. This will make applications more flexible and make it easier to maintain not only other versions of the framework as they come out, but the complete process of overriding classes in ExtJS. This way there is no need to edit the core code of the framework to modify its functionality. Remember, it is bad practice to edit the core code of any framework. You will be tied to an old version, and this might cause your code to not work anymore. Finally, I reviewed how to change a class behavior by its definition, changing all of its instances and subclasses.


  • http://da-14.com Dmitriy Sushko

    Thank you, Armando for such detailed explanation.

    I found one problem in the article – perhaps we need to put the Overrides instead of Ext namespace here:

    Ext.define(‘Ext.data.Store’, {
    override :’Ext.data.Store’,

    removeAll : function () {
    this.clearFilter(); //clear any filters than remove
    this.callParent(arguments);
    }
    });


What We Do

We’ll work closely with your team to instill Lean practices for ideation, strategy, design and delivery — practices that are adaptable to every part of your business.

See what Modus can do for you.

We're Hiring!

Join our awesome team of dedicated engineers.

Loading...