mabello
3 Apr 2008, 6:45 AM
I was looking to the surce code of DataReader and all the sublcasses of that, and I found something that I'd like to discuss.
Without looking at the source code at the beginning, I though that the dataReaders must be interchangeable each other without problem based on what data you need to read, so that the DataProxy can use whatever DataReader (Array Json, ...)
JsonReader defines 2 public method read and readRecords, but the comment say that read is only used by a DataProxy (meaning that DataProxy can not use ArrayReader correctly in my opinion)
/**
* This method is only used by a DataProxy which has retrieved data from a remote server.
* @param {Object} response The XHR object which contains the JSON data in its responseText.
* @return {Object} data A data block which is used by an Ext.data.Store object as
* a cache of Ext.data.Records.
*/
read : function(response){
Analyzing ArrayReader, you can see that it does not defined read, so it inherits read function from JsonReader, but of course in my opinion it is not a clear design, because I think you can not call read in a instance of ArrayReader otherwise you will have an error, so that you have ArrayReader and JsonDataReader with a "different interface contract"; furthemore, ArrayReader , a class that extend JsonReader has "less" functionality than the base class...so why inherit ArrayReader from JsonReader, if they not share anything and there is no one call to the super class?
Besides, in case you want to use an ArrayReader within a grid with pagination (I mean the store linked to the grid is using an instance of ArrayReader) your paging toolbar will have problem to display the real totalRecord of your dataset, because the property totalRecords is calculated based on the length of the element cotained in the underlying array.
readRecords : function(o){
var sid = this.meta ? this.meta.id : null;
var recordType = this.recordType, fields = recordType.prototype.fields;
var records = [];
var root = o;
for(var i = 0; i < root.length; i++){
var n = root[i];
var values = {};
var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
for(var j = 0, jlen = fields.length; j < jlen; j++){
var f = fields.items[j];
var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
var v = n[k] !== undefined ? n[k] : f.defaultValue;
v = f.convert(v, n);
values[f.name] = v;
}
var record = new recordType(values, id);
record.json = n;
records[records.length] = record;
}
return {
records : records,
totalRecords : records.length//************************
};
}
So in my application I had to override the read function of array to have the same functionality of a JsonReader (I had to do so because I have impemented a specialized DataProxy used with AjaxPro, but it is not the point)
Ext.override(Ext.data.ArrayReader, {
read : function(reponse) {
var o = reponse;
if(typeof this.meta.beforeReadRecords == 'function' && this.meta.beforeReadRecords != null)
o = this.meta.beforeReadRecords(reponse);
var result = this.readRecords(o);
if(typeof this.meta.afterReadRecords == 'function' && this.meta.afterReadRecords != null)
this.meta.afterReadRecords(result, reponse);
return result;
}
});
In beforeReadRecords, you can pre-elaborate your response.
In afterReadRecords, you can modify the result to achieve your goals (for example to set correctly to the result the property totalRecords based on the response received from the server.
That's how i use the array reader in my code:
var dataReaderMappingCfg = [{name: this.dataFieldName}];
var meta = {
dataSetPropertyNameArray: ['value', 'dataSet'],
totalCountsPropertyNameArray: ['value', 'totalCounts'],
beforeReadRecords : function(response){
return TI.Util.PropertyFinder(response, this.dataSetPropertyNameArray)
},
afterReadRecords : function(result, response){
result.totalRecords = TI.Util.PropertyFinder(response, this.totalCountsPropertyNameArray);
}
}
this.dataReader = new Ext.data.ArrayReader(meta, dataReaderMappingCfg);
What do you think?
Regards
Without looking at the source code at the beginning, I though that the dataReaders must be interchangeable each other without problem based on what data you need to read, so that the DataProxy can use whatever DataReader (Array Json, ...)
JsonReader defines 2 public method read and readRecords, but the comment say that read is only used by a DataProxy (meaning that DataProxy can not use ArrayReader correctly in my opinion)
/**
* This method is only used by a DataProxy which has retrieved data from a remote server.
* @param {Object} response The XHR object which contains the JSON data in its responseText.
* @return {Object} data A data block which is used by an Ext.data.Store object as
* a cache of Ext.data.Records.
*/
read : function(response){
Analyzing ArrayReader, you can see that it does not defined read, so it inherits read function from JsonReader, but of course in my opinion it is not a clear design, because I think you can not call read in a instance of ArrayReader otherwise you will have an error, so that you have ArrayReader and JsonDataReader with a "different interface contract"; furthemore, ArrayReader , a class that extend JsonReader has "less" functionality than the base class...so why inherit ArrayReader from JsonReader, if they not share anything and there is no one call to the super class?
Besides, in case you want to use an ArrayReader within a grid with pagination (I mean the store linked to the grid is using an instance of ArrayReader) your paging toolbar will have problem to display the real totalRecord of your dataset, because the property totalRecords is calculated based on the length of the element cotained in the underlying array.
readRecords : function(o){
var sid = this.meta ? this.meta.id : null;
var recordType = this.recordType, fields = recordType.prototype.fields;
var records = [];
var root = o;
for(var i = 0; i < root.length; i++){
var n = root[i];
var values = {};
var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
for(var j = 0, jlen = fields.length; j < jlen; j++){
var f = fields.items[j];
var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
var v = n[k] !== undefined ? n[k] : f.defaultValue;
v = f.convert(v, n);
values[f.name] = v;
}
var record = new recordType(values, id);
record.json = n;
records[records.length] = record;
}
return {
records : records,
totalRecords : records.length//************************
};
}
So in my application I had to override the read function of array to have the same functionality of a JsonReader (I had to do so because I have impemented a specialized DataProxy used with AjaxPro, but it is not the point)
Ext.override(Ext.data.ArrayReader, {
read : function(reponse) {
var o = reponse;
if(typeof this.meta.beforeReadRecords == 'function' && this.meta.beforeReadRecords != null)
o = this.meta.beforeReadRecords(reponse);
var result = this.readRecords(o);
if(typeof this.meta.afterReadRecords == 'function' && this.meta.afterReadRecords != null)
this.meta.afterReadRecords(result, reponse);
return result;
}
});
In beforeReadRecords, you can pre-elaborate your response.
In afterReadRecords, you can modify the result to achieve your goals (for example to set correctly to the result the property totalRecords based on the response received from the server.
That's how i use the array reader in my code:
var dataReaderMappingCfg = [{name: this.dataFieldName}];
var meta = {
dataSetPropertyNameArray: ['value', 'dataSet'],
totalCountsPropertyNameArray: ['value', 'totalCounts'],
beforeReadRecords : function(response){
return TI.Util.PropertyFinder(response, this.dataSetPropertyNameArray)
},
afterReadRecords : function(result, response){
result.totalRecords = TI.Util.PropertyFinder(response, this.totalCountsPropertyNameArray);
}
}
this.dataReader = new Ext.data.ArrayReader(meta, dataReaderMappingCfg);
What do you think?
Regards