A Dive Into the Sencha Class Config System

   Sencha
A Dive Into the Sencha Class Config System

From the very beginning the Ext JS framework has implemented a class system to extend JavaScript. The goal of the class system was to support efficient code organization and implement a pseudo-classical inheritance found in many Object Oriented programming languages.

With the release of Ext JS 4.0, Sencha decided to revisit their class system and enhance it with more object oriented goodies. In particular they developed a config system, their answer to properties. This blog post will dive into the config system and how it is used in Ext JS 4.x, 5.x and Sencha Touch 2.x.

TL;DR on the Sencha Class System

The Sencha class system is the foundation of the entire framework family, beginning with a class known as Ext.Base. With only a few exceptions, classes must follow a particular naming convention directly related to their file path.

Here is a sample Sencha class definition, instantiation and usage: View on Fiddle

// Define class with name "Car"
Ext.define('Car', {
    // Define config properties
    config : {
        make  : undefined,
        model : undefined
    },
    // First method that gets called upon class instantiation
    constructor : function (config) {
        // Initializes config properties
        this.initConfig(config);
    },
    // Define drive method
    drive : function () {
        console.log('Driving ' + this.getMake() + ' ' + this.getModel());
    }
});

// Instantiate class "Car" with config properties
var car = Ext.create('Car', {
    make  : 'Honda',
    model : 'Accord'
});

// Call method "drive" on class instance
// Outputs "Driving Honda Accord" to the console
car.drive();

The Config System

You may notice that we defined a couple of config properties in that class example. Let’s dive into what happens under the hood. The JavaScript interpreter treats the function argument as a plain object with a key “config” and it has a couple of child members. However, during the class instantiation process the method initConfig is called. As described, it initializes the config system for that class instance. The config system then registers the associated property config methods with the class instance.

Config Methods

Getter

Standard accessor method that returns the current value of the property. This is an auto-generated function by the config system. View on Fiddle

car.getMake(); // returns “Honda”

Setter

Mutator method that sets the value of the property on the class instance. This is also an auto-generated function by the config system. View on Fiddle

car.setMake(“Toyota”);
car.getMake(); // returns “Toyota”

Applier

This function gets called by the setter when the configuration property changes (e.g. goes from undefined to “Foo”). The applier must return a value; this value will be the new value of the configuration property. The applier is auto-generated by the config system and is generally overridden to execute some kind of logic before setting the value.

View on Fiddle

// Example applier definition
applyMake : function (newValue, oldValue) {
    // Execute some arbitrary logic
    if(oldValue.length > newValue.length) {
        return oldValue.toUpperCase();
    } 
 
    return newValue.toUpperCase(); 
}

Updater

The updater function gets called by the setter after the applier when the value for the configuration changes (e.g. going from “Foo” to “Bar”). The updater is generally used by a class as a reaction to a config property changing.

View on Fiddle

// Example updater definition
updateModel : function (newValue, oldValue) {
    if(newValue === 'Accord') {
        this.setMake('Honda');
    } else if(newValue === 'Camry') {
        this.setMake('Toyota');
    }
}

Potential Scenarios

  • Change a UI element of a component based on a property change. View on Fiddle
// Enable Drive button if make is set
applyMake : function (newValue, oldValue) {
    if(newValue) {
      this.down('button#drivebutton').enable();
    }
    return newValue;
}
  • Instantiate a required dependency once a config value is set.

Example: instantiate and/or load a Store if a URL is passed to class. View on Fiddle

   
// Instantiate a store if "storeUrl" config property is set
applyStoreUrl : function (url) {
    if(url) {
        this.setStore(Ext.create('Ext.data.Store', {
            fields : ['name'],
            proxy  : {
                type : 'ajax',
                url  : url,
            }
        }));
    }
       
    return url;
}
  • Instantiate a child class based on a config value.

Example: add a toolbar to a Panel. View on Fiddle

// Instantiate Ext.Toolbar with config and return class instance
applyHeaderToolbar : function (cfg) {
    if(cfg) {
        var tbar = this.tbar = Ext.create('Ext.Toolbar', cfg);
        return tbar;
    }
}

Ext JS 4 vs Ext JS 5 vs Sencha Touch 2

Even though Ext JS 4, 5 and Sencha Touch 2 share the same class system there are some differences regarding the role of the config system in the frameworks.

  • In Ext JS 4 the config system took the back seat. Quite frankly it was rarely (if ever) used by the framework itself. Therefore many developers overlooked its existence all together.

  • In Ext JS 5.x, Sencha began integrating the config system into its framework. Ext JS now initializes the config system at the Component level. With this, all components utilize config properties instead of object properties. A new feature of in the Ext JS 5 config system is that custom setters can now callParent to the automatically generated setter by the class system.

  • Sencha Touch 2 was a major paradigm shift from its predecessor. This allowed Sencha the flexibility to start from scratch and do things “right”. What this meant in terms of the class system, was to enforce the config system throughout the entire framework. Sencha Touch 2 requires you to use the config system to manipulate class properties. It internally leverages the system to its full potential.

In summary, Ext JS 4 and Sencha Touch 2 can be considered the extremes of config system integration. Ext JS 5 sits somewhere in between due its backwards compatibility with Ext JS 4.

Related Reading


Like What You See?

Got any questions?