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.
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:
This is the store behavior:
- First I filter my data by clicking the โFilterโ button, which will then display all the records where id is greater than 10.
- Then, I will remove all the records from the store by clicking the โRemove Allโ button.
- 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.
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.
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.
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.
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.
Jay Garcia
Related Posts
-
Ext JS to React: Migration to Open Source
Worried about Migrating from Ext JS? Modus has the Answers Ideraโs acquisition of Sencha has…
-
The Top 6 Things We Love About Ext JS 6
โSencha Ext JS is the most comprehensive MVC/MVVM JavaScript framework for building feature-rich, cross-platform web…