In a previous post, my colleague Stan explained the foundation of the Sencha Config System and how the getters
and setters
work. In this post, I’m going to explain the new Ext.Config
features that are available in Ext JS 6. You can also learn more by reading the Ext JS 6 docs.
Ext.Config.cached
When set as true, the config property will be stored on the class prototype once the first instance has had a chance to process the default value.
config: { foo: { $value: 42, cached: true } }
You can find a basic example in this Fiddle, and look at the following gif:
An implementation can be found in Ext.util.ElementContainer.childEls
property. Caching childEls
into the prototype
saves memory. Some CPU cycles are also saved in the configuration phase during class instantiation.
childEls: { $value: {}, cached: true, lazy: true, merge: function (newValue, oldValue, target, mixinClass) {
Checking for cached
configs is easy by accessing the cachedConfigs
property through the getConfigurator()
method:
myObj.self.getConfigurator().cachedConfigs
This is possible because of the Ext.Configurator
utility class, which is instantiated the first time you call the getConfigurator()
for a specific class.
Ext.Config.evented
If this is set as true, the config property will be treated as an Ext.Evented
. This means that whenever the setter
of this config is called, Ext JS will automatically fire an event [configname + change]. Note that you have to include the Ext.mixin.Observable
mixin and call its constructor
in the defined class constructor
to initialize the mixin
.
Ext.define('MyClass', { mixins: ['Ext.mixin.Observable'], config: { foo: { $value: 42, evented: true } }, constructor: function(config) { console.log('MyClass Instantiated'); this.initConfig(config); this.mixins.observable.constructor.call(this, config); return this; } }); myObj = new MyClass(); myObj.on('foochange', function() { console.log(arguments); });
You can find a basic example in this Fiddle and look at the following gif:
Another way of defining evented
configs is by using the eventedConfig
of the Ext.Evented
class, which is processed in onClassExtended
phase:
Ext.define('MyEventedClass', { extend: 'Ext.Evented', eventedConfig: { boo: 34 }, constructor: function(config) { this.initConfig(config); this.mixins.observable.constructor.call(this, config); return this; } }); myEventedObj = new MyEventedClass(); myEventedObj.on('boochange', function() { console.log('boochange'); console.log(arguments); });
The defined class has to extend the Ext.Evented
to create the evented
configs. An implementation of this approach can be found in the Ext.Widget.width
property.
Ext.Config.lazy
If a lazy config is set as true, the config property will not be immediately initialized during the initConfig
call.
config: { foo: { $value: 42, lazy: true } }
You can find a basic example in this Fiddle and by looking at the following gif:
An implementation can be found in Ext.app.Application.mainView
property where the mainView
is created lazily. So performance-wise, it’s created when it’s used, not when the app is instantiated.
Ext.Config.merge
The merge
config accepts a function which will be called as instances are created or derived classes are defined. The merge function accepts the new values and the inherited value and returns the combined config value. On further calls, that returned value will be provided as oldValue
through an argument:
Ext.define('MyClass', { config: { foo: { $value: [42], merge: function(newValue, oldValue) { var val = [].concat(newValue, oldValue); return val; } } }, constructor: function(config) { this.initConfig(config); return this; } }); Ext.define('MyExtendedClass', { extend: 'MyClass', foo: [23] }); var myObj = new MyClass({ foo: 123 }); //MyClass.foo: – [123, 42] var myExtendedObj = new MyExtendedClass({ foo: 321 }); //MyExtendedClass.foo: – [321, 23, 42]
You can find a basic example in this Fiddle and by looking at the following screenshot:
An implementation can be found in Ext.panel.Header.title
property where the merge
config is used for merging a given title
config with the default one:
title: { $value: { xtype: 'title', flex: 1 }, merge: function(newValue, oldValue) { if (typeof newValue !== 'object') { newValue = { text: newValue }; } return Ext.merge(oldValue ? Ext.Object.chain(oldValue) : {}, newValue); } }
Also, you could use the Ext.Config.mergeSets
method to do your merges:
twoWayBindable: { $value: null, lazy: true, merge: function (newValue, oldValue) { return this.mergeSets(newValue, oldValue); } }
Conclusion
Ext JS provides a lot of components and an easy way to extend them or build new ones. The Config System has a big role in achieving that, and it’s a core part of the framework. Besides that, it’s the best and most powerful Config System we’ve seen in a framework. If you’re working on your custom components, check out these suggestions and let us know how you used the configs.
This post was originally published on the Sencha blog.
Vadim Popa
Related Posts
-
A Dive Into the Sencha Class Config System
From the very beginning the Ext JS framework has implemented a class system to extend…
-
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…