Being used in developpement stage of our current projet, my extension keeps to be updated.
Changes since first version :
- optimized code : the field definition of the records are only parsed once. It was parsed for every returned row in the last version
- added static Ext.data.BeanRecord.createFromBean(bean) function that creates a record directly from a bean (usefull for example in order to populate a form via form.loadRecord(beanRecord)).
Future version will include a proxy Store using a modified "PagingMemoryProxy" implementation in order to be able to define a store able to do local paging from a defined SeamRemotingStore. The proxy is already prototyped but needs to be package in some smart form of a store encapsulation at once the paging store and the proxied SeamRemotingStore. This kind of store can be VERY usefull in case of a SeamRemotingStore having 1000+ rows. The grid cannot handle so much data (moving, sorting, rendering in general veryyyy slow), so we needed to add a pager to it (without compromising the needed functionnality to have all rows loaded on client-side !).
Download complete file here.
Affichage des articles dont le libellé est Store. Afficher tous les articles
Affichage des articles dont le libellé est Store. Afficher tous les articles
lundi 11 février 2008
vendredi 18 janvier 2008
Seam + ExtJS, Store, Reader, Proxy
Passons maintenant à la pratique. Je commencerai pas exposer les différentes classes côté ExtJS qui permettent de dialoguer avec Seam Remoting. Pour cela, je suis parti de l'exemple d'extension pour DWR proposé par Axel ici : http://extjs.com/forum/showthread.php?t=19529
Now it's time for some code examples. I'm begining to expose the different ExtJS extensions classes which permit to dialog with Seam Remoting. For this purpose, I started with the example extension for DWR proposed by Axel in the ExtJS User Extensions forum : http://extjs.com/forum/showthread.php?t=19529
Now it's time for some code examples. I'm begining to expose the different ExtJS extensions classes which permit to dialog with Seam Remoting. For this purpose, I started with the example extension for DWR proposed by Axel in the ExtJS User Extensions forum : http://extjs.com/forum/showthread.php?t=19529
/**
* Seam remoting proxy.
*
* Can be bound to any WebMethod which signature is like :
* - ResultList<T> webMethod(QueryParam param) for a non paging method.
* - PagingResultList<T> webMethod(PagingQueryParam param) for a paging method.
*
* @param {function} f Points to remote function.
* @param {Object} o Seam component.
* @param {boolean} paging Tells wether the remote method uses paging.
*/
Ext.data.SeamRemotingProxy = function(f, o, paging)
{
Ext.data.SeamRemotingProxy.superclass.constructor.call(this);
this.func = f;
this.instance = o;
this.paging = paging;
};
Ext.extend(Ext.data.SeamRemotingProxy, Ext.data.DataProxy,
{
/**
* Builds a query parameter object (queryParam or pagingQueryParam
* if paging is used by the remote method).
*
* Calls the seam remote method by passing to it the query parameter
* objet and the callback function.
*
* @param {Object} params Object with following fields defined : queryString,
* and if paging enabled, with following more fields : start, limit.
* @param {Object} reader
* @param {Object} loadCallback
* @param {Object} scope
* @param {Object} arg
* @param {Object} remoteArgs
*/
load: function(params, reader, loadCallback, scope, arg, remoteArgs)
{
var dataProxy = this;
dataProxy.fireEvent("beforeload", dataProxy, params);
var args = [];
// Wether the remote method method support paging or not,
// choose the right parameter class.
var queryParamComponentName;
if (this.paging)
{
queryParamComponentName = "pagingQueryParam";
}
else
{
queryParamComponentName = "queryParam";
}
var queryParam = Seam.Component.newInstance(queryParamComponentName);
//
for (var param in params)
{
queryParam[param] = params[param];
}
args[args.length] = queryParam;
args[args.length] = function(response)
{
dataProxy.fireEvent("load", dataProxy, response, loadCallback);
var records = reader.read(response);
if (records.records.length > 0)
{
scope.fields = records.records[0].fields;
}
loadCallback.call(scope, records, arg, true);
}
this.func.apply(this.instance, args);
}
});
/**
* Extension of Ext.data.Record to handle bean data.
* Extends record.get(name) in order to be able to access
* properties of underlying objects like bean.child.property.
*
* @param {Object} data
* @param {Object} id
*/
Ext.data.BeanRecord = function(data, id)
{
Ext.data.BeanRecord.superclass.constructor.call(this, data, id);
};
Ext.extend(Ext.data.BeanRecord, Ext.data.Record, {});
Ext.data.BeanRecord.create = function(o)
{
var f = Ext.data.Record.create.call(this, o);
/**
*
* @param {String} name
*/
f.prototype.get = function(name)
{
var names = name.split('.', 2);
if (names.length > 1)
{
var o = this.data[names[0]];
if (o)
{
var result = eval("o." + names[1]);
return result;
}
else
{
return "";
}
}
else
{
return this.data[name];
}
}
/**
* Copies a record and its underlying seam data bean.
* @param {String} componentName The seam component name of the underlying bean.
*/
f.prototype.copyRecord = function(componentName)
{
var copieRecord = this.copy();
var copieData = copyBean(this.data, componentName);
copieRecord.data = copieData;
return copieRecord;
}
return f;
};
/**
* Extends Ext.data.DataReader in order to read bean data.
*/
Ext.data.BeanReader = function()
{
Ext.data.BeanReader.superclass.constructor.call(this, null, []);
};
Ext.extend(Ext.data.BeanReader, Ext.data.DataReader,
{
read: function(response)
{
var records = [];
var bean;
for (var i = 0; i < response.list.length; i++)
{
bean = response.list[i];
// retreives the bean field names
var fields = [];
for (var prop in bean)
{
if ((new String(bean[prop])).substring(0, 8) != "function")
{
fields[fields.length] = prop;
}
}
// builds dynamically the record definition
var recordDefinition = "[";
var field;
for (var j = 0; j < fields.length; j++)
{
field = fields[j];
recordDefinition = recordDefinition + "{name: '" + field + "'}";
if (j < fields.length - 1)
{
recordDefinition = recordDefinition + ",";
}
}
recordDefinition = recordDefinition + "]";
var ObjectRecord = eval("Ext.data.BeanRecord.create(" + recordDefinition + ")");
// record instantiation
var myNewRecord = new ObjectRecord();
// record data is the bean
myNewRecord.data = bean;
records[records.length] = myNewRecord;
}
return {
records: records,
totalRecords: response.totalRecords
};
}
});
/**
* [en]
* Added configuration parameters :
* - remoteComponent (Object) : Seam component resulting from a call to
* Seam.Component.getInstance(name)
* - remoteComponentName (String) : Seam component name to remote-access.
* This parameter is non used if remoteComponent is defined.
* - remoteMethodName (String) : Web remote method name (annotated @WebRemote)
* - paging (bool) - optional (false by default) : tells wether the remote method uses paging.
*
* Use example :
*
* var store = new Ext.data.SeamRemotingStore(
* {
* remoteComponent: customerWebAction,
* remoteMethodName: "listAllCustomersWithPaging",
* paging: true,
* sortInfo:
* {
* field: 'nom',
* direction: "ASC"
* },
* groupField: 'customerType'
* });
*
* store.load(
* {
* params:
* {
* queryString: '',
* start: 0,
* limit: 15
* }
* });
*
* [fr]
* Paramètre de configurations supplémentaires :
* - remoteComponent (object) : Composant seam obtenu par un appel à Seam.Component.getInstance(name)
* - remoteComponentName (String) : nom du composant Seam à consulter (paramètre non pris en compte si le précédent est défini)
* - remoteMethodName (String) : nom de la méthode remote (marquée @WebRemote)
* - paging (bool) - optionnel (false par défaut) : la méthode remote supporte la pagination
*
* @param {Config} c
*/
Ext.data.SeamRemotingStore = function(c)
{
// configuration
var seamComponent = c.remoteComponent;
if (!c.remoteComponent)
{
var remoteComponentName = c.remoteComponentName;
seamComponent = Seam.Component.getInstance(remoteComponentName);
}
var remoteMethodName = c.remoteMethodName;
var paging;
if (c.paging)
{
paging = c.paging;
}
else
{
paging = false;
}
var remoteMethod = eval("seamComponent." + remoteMethodName);
// instantiale a proxy and a reader
this.proxy = new Ext.data.SeamRemotingProxy(remoteMethod, seamComponent, paging);
this.reader = new Ext.data.BeanReader();
// record currently selected
this.currentRecord = null;
this.getCurrentRecord = function()
{
return this.currentRecord;
}
this.setCurrentRecord = function(record)
{
this.currentRecord = record;
}
Ext.data.SeamRemotingStore.superclass.constructor.call(this, c);
};
Ext.extend(Ext.data.SeamRemotingStore, Ext.data.GroupingStore);
/**
* Utility method to create a copy of a bean knowing it's seam
* component name.
*
* @param {Object} bean The bean to be copied
* @param {String} beanName Seam component name
*/
function copyBean(bean, beanName)
{
var newBean = Seam.Component.newInstance(beanName);
for (var prop in bean)
{
if ((new String(bean[prop])).substring(0, 8) != "function")
{
newBean[prop] = bean[prop];
}
}
return newBean;
}
Inscription à :
Articles (Atom)