Reputation: 33
Hi Im a novice in ExtJs script, im trying to develop custom multifield, i was able to understand the node creation part, but in the scripting part im unable to catch some of the things like in listener adding scope:this, fn:this.updatehidden i tried to google out the answer but i din get any satisfactory answer. so could any one please explain me the scope:this part and why we call superclass constructor in the initcomponent,any related resources are also welcome
Thanks in advance Love to code
Ejst.CustomWidget = CQ.Ext.extend(CQ.form.CompositeField, {
/**
* @private
* @type CQ.Ext.form.TextField
*/
hiddenField: null,
/**
* @private
* @type CQ.Ext.form.ComboBox
*/
allowField: null,
/**
* @private
* @type CQ.Ext.form.TextField
*/
otherField: null,
constructor: function(config) {
config = config || { };
var defaults = {
"border": false,
"layout": "table",
"columns":2
};
config = CQ.Util.applyDefaults(config, defaults);
Ejst.CustomWidget.superclass.constructor.call(this, config);
},
// overriding CQ.Ext.Component#initComponent
initComponent: function() {
Ejst.CustomWidget.superclass.initComponent.call(this);
this.hiddenField = new CQ.Ext.form.Hidden({
name: this.name
});
this.add(this.hiddenField);
this.allowField = new CQ.form.Selection({
type:"select",
cls:"ejst-customwidget-1",
listeners: {
selectionchanged: {
scope:this,
fn: this.updateHidden
}
},
optionsProvider: this.optionsProvider
});
this.add(this.allowField);
this.otherField = new CQ.Ext.form.TextField({
cls:"ejst-customwidget-2",
listeners: {
change: {
**scope:this,
fn:this.updateHidden**
}
}
});
this.add(this.otherField);
},
// overriding CQ.form.CompositeField#processPath
processPath: function(path) {
console.log("CustomWidget#processPath", path);
this.allowField.processPath(path);
},
// overriding CQ.form.CompositeField#processRecord
processRecord: function(record, path) {
console.log("CustomWidget#processRecord", path, record);
this.allowField.processRecord(record, path);
},
// overriding CQ.form.CompositeField#setValue
setValue: function(value) {
var parts = value.split("/");
this.allowField.setValue(parts[0]);
this.otherField.setValue(parts[1]);
this.hiddenField.setValue(value);
},
// overriding CQ.form.CompositeField#getValue
getValue: function() {
return this.getRawValue();
},
// overriding CQ.form.CompositeField#getRawValue
getRawValue: function() {
if (!this.allowField) {
return null;
}
return this.allowField.getValue() + "/" +
this.otherField.getValue();
},
// private
updateHidden: function() {
this.hiddenField.setValue(this.getValue());
}
});
// register xtype
CQ.Ext.reg('ejstcustom', Ejst.CustomWidget);
Upvotes: 2
Views: 374
Reputation: 20244
You are calling the superclass initComponent function because you want the functionality of the derived class's hierarchy to be available.
For example, if you want to construct an elephant:
If you would use the standard ExtJS syntax for this (not sure whether CQ has it's own "standard syntax"), the elephant definition would look like this:
Ext.define('Elephant',{
extend:'Mammal',
initComponent:function() {
var me = this;
// set config properties. Two possible calls:
// "Ext.apply" overwrites config properties already defined by the subclass before constructor has been called
// "Ext.applyIf" only sets config properties that have NOT been set by the subclass!
// Since a MiniElephant subclass may want to set size:"small", we use applyIf here.
Ext.applyIf(me,{
size:'big',
color:'gray'
});
me.callParent(arguments); // <- call constructor of superclass
me.addTrunk(); // <- postprocessing
},
addTrunk:function() {
var trunk = Ext.create('Trunk',{
...
});
me.getHead().add(trunk);
// since addTrunk is called after the mammal constructor has been executed,
// the head is already initialized and the getHead function available!
}
});
Ext.define('Mammal',{
extend:'Animal',
initComponent:function() {
var me = this;
// Every mammal has a head, so we force the property into here using "apply"!
Ext.apply({
hasHead:true,
...
});
me.callParent(arguments); // <- construct animal
me.addBreast(); // <- add breast
},
getHead:function() {
return this.headerEl;
},
...
});
A listener is a function. Every function has a so-called scope
, which is the object that you will get when you access this
from inside the function. As long as you don't use this
inside your function, the scope
doesn't matter to you.
By default, in JavaScript, the scope of a function is the object that the function is attached to, so if you have an object
var listeners = { update:function() { console.log(this); } };
and if you call the function like this:
listeners.update()
it will log the listeners object to the console; but if you do it like this:
var fn = listeners.update;
fn();
it won't! The scope of a function can be set if you call the function:
listeners.update.call(myScope, firstParameter, secondParameter, ...)
or if you apply it:
listeners.update.apply(myScope, parameterArray)
(Good to remember: Apply takes the Array!)
Since, in ExtJS, the listeners configuration is processed by an Observable mixin, which puts the functions into specially crafted sub-objects, the default scope won't make sense at all to an ExtJS programmer, so they have changed it. And for convenience, ExtJS has added a config property that can be used by the programmer to define his intended scope
of the function.
So if you define a panel and add a field inside:
Ext.apply(me, {
items:[{
xtype:'textfield',
listeners:{
update:function() {
console.log(this); // <- returns the panel, because...
},
scope:me // <- we are scoping to the panel!
}
}
});
Upvotes: 2