PDA

View Full Version : Ext.twensoc.StaticParentCombo



Ronaldo
21 Jul 2009, 11:47 PM
Hi all,

Here's a combobox, to be used in an editable grid, that can handle the following data structure:



{
rows: [{
id: 1,
name: 'Twensoc',
role: { <-- Notice that the role is a parent of the 'user'/'row'
id: 1, and is defined as an object
name: 'admin'
}
}]
}


It took me a while to get this right, so I thought I might as well share it with you. Please see the comments in the code for the complete explanation.



/**
* @class Ext.twensoc.StaticParentCombo
* @extends Ext.grid.GridPanel
*
* <p>This is an inherited version of the Ext.form.ComboBox, meant to be used in
* an editable grid. My java FlexJson library returns the json mentioned below,
* and that json is incompatible with the structure expected by the default
* ext combobox. </p>
* <p>This combobox can handle only static data, and therefore it is suitable for selecting
* static data (ie it won't request data from the server, but expects the choices to be defined).</p>
* <p>The sole purpose of this component is to be able to use
* the following data structure in your record:</p>
* <pre><code>
* {
* rows: [{
* id: 1,
* name: 'Twensoc',
* role: { <-- Notice that the role is a parent of the 'user'/'row'
* id: 1, and is defined as an object
* name: 'admin'
* }
* }]
* }
* </pre></code>
* <p>There's no role_id in the record itself. Instead, the 'role' field is an object,
* containing an id and a name. This combo can handle the 'role' field, and will display
* the 'name' field of the object (ie role.name). You can use it in your grid's column model like this:</p>
* <pre><code>
* grid.cm = new Ext.grid.ColumnModel([
* {name:'id', id:'id', header:'Id', dataIndex:'id'},
* {name:'name', header:'name', dataIndex:'name', width: 200, editor: new Ext.form.TextField({allowBlank:false}) },
* {name:'role.name', header: 'Role', dataIndex:'role',
* editor: new Ext.twensoc.ParentRelationCombo({
* recordField: 'role',
* data: [[1, 'guest'], [99, 'admin']]
* }),
* renderer: function(v,f,r) {
* return r ? r.data.role.name : '';
* }
* }
* ]);
* </pre></code>
* <p>The mapping is simple:</p>
* <pre><code>
* this.mapping = [
* {name:'id'},
* {name:'name'},
* {name:'role'} // will contain an object: {id: x, name: y}
* ];
* </pre></code>
* <p>Don't forget to create the namespace!</p>
* <p>Ext.twensoc.StaticParentCombo is licensed under the terms of the Open Source GPL 3.0 license.</p>
*
* @constructor
* @param {string} recordField Name of the field that contains the parent data.
* @param {data} data Data to choose from. Example: [[1, 'guest'], [99, 'admin']]
*/

// Remove comments if this namespace is not yet defined.
//Ext.namespace('Ext.twensoc');

Ext.twensoc.StaticParentCombo = Ext.extend(Ext.form.ComboBox, {
typeAhead: true,
triggerAction: 'all',
lazyRender:true,
mode: 'local',
valueField: 'id',
displayField: 'name',
listClass: 'x-combo-list-small',
/**
* Initialization
*/
initComponent: function(){
this.store = new Ext.data.ArrayStore({
id: 0,
fields: this.fields || ['id','name'],
data: this.data
});
Ext.twensoc.StaticParentCombo.superclass.initComponent.call(this);
this.on('beforerender', this.onBeforeRender, this);
},
/**
* Called once. Attach an event listener to the 'complete' event.
*/
onBeforeRender: function(combo) {
this.gridEditor.on("complete", this.onEditComplete, this);
},
/**
* Because the gridEditor's onEditComplete method assumes either an int or a string value,
* (and we have an object here), the 'String(value) !== String(startValue)' check will always fail.
* Therefore, we've attached another listener, who's sole purpose is to set the record's field value
* and mark that field as modified.
*/
onEditComplete : function(ed, value, startValue) {
ed.record.set(this.recordField, this.value);
},
/**
* Override the combo's onSelect method in order to change the this.setValue call.
*/
onSelect : function(record, index){
if(this.fireEvent('beforeselect', this, record, index) !== false){
this.setValue({id:record.data.id, name:record.data.name});
this.collapse();
this.fireEvent('select', this, record, index);
}
},
/**
* Override the setVaue method. The v(alue) parameter is expected to be an object
* like in {id: 1, name:'combotext'}
*/
setValue : function(v){
this.lastSelectionText = v.name;
Ext.form.ComboBox.superclass.setValue.call(this, v.name); // hack: skip the Ext.Form.Combobox.setValue
this.value = v;
return this;
},
/**
* The this.value variable contains the object (' {id: 1, name:'combotext'} '),
* and we should either return that or an empty string.
*/
getRawValue : function() {
var v = this.value ? this.value : '';
if (v === this.emptyText) {
v = '';
}
return v;
},
/**
* This method is either called with a string paramter or an object parameter,
* and is used to process the value before calling the validate method.
* The validate method expects a string, so always return a string here.
*/
processValue : function(v){
if(Ext.isObject(v)) {
return v.name
}
return v;
}
});



Any comments or improvements are welcome!

Best regards,
Ronaldo