PDA

View Full Version : Splitting a response into separate stores



geewhizbang
4 Aug 2009, 9:35 AM
I have a DirectStore (or JsonStore) response that needs to be split out by CategoryName.

It is returned already sorted by category name if that helps.

I know I could loop thru the response itself and build up each datastore and then stuff them into a grid to display them, but that would probably be a hack, especially if there is a built in method to do this.

If there is a document I can read about this or a good example to show me, it would be great.

zhegwood
4 Aug 2009, 2:58 PM
In the past, I've cycled through like this



var store1 = new Ext.data.JsonStore({
fields: [{...}]
})
var store2 = new Ext.data.JsonStore({
fields: [{...}]
});
initialstore.each(function(record){
if (record.get('fieldname') === 'value') {
store1.add(record);
} else if (record.get('fieldname') === 'othervalue') {
store2.add(record);
}
},this);
delete(store);


You could also splice the store.data.items array and load that array into a new store, but I'm not sure that's any more or less efficient.

Or, instead of creating the initial store in the first place, find the splice point of the json data array, and load the arrays into two sets of store data.

rmd
15 Jul 2010, 2:17 AM
Hi, I'm having the same problem. I still don't get it on how it could be done. Can you post a sample code here. Thanks

hendricd
15 Jul 2010, 5:58 AM
@geewhiz --

You hadn't mentioned the size of your resultsets, but perhaps that doesn't matter. You could add a couple-o-helpers and the data.Store class could do your bidding (pseudo-coded here):



/**
* Store cloning method
*/
Ext.override(Ext.data.Store,{
clone : function(withData){
var records = [];
withData !== false &&
this.each(function(record){ records.push( record.copy() ); });

var tStore = new (this.constructor)({
recordType: this.recordType,
reader : this.reader,
writer : this.writer,
proxy : this.proxy,
fields : this.fields,
sortInfo : Ext.apply({}, this.sortInfo || {}),
multiSortInfo : Ext.apply({}, this.multiSortInfo || {})
});

records.length && tStore.add(records);
return tStore;
}
});
A simple shuffle:


var store1 = new Ext.data.JsonStore({ fields: [{...}], .....}),
store2;

store1.load({ //load them all here
params : {....},
callback : function(recs, options, success){
if(success){
store2 = this.clone();
this.filterBy( function(rec){ return rec.isWhatIWant; } );
store2.filterBy( function(rec){ return rec.isOppositeWhatIWant; } );

someGrid2.reconfigure(store2, someGrid2.getColumnModel());

}
}
});
or something that might survive paging, etc:



var store1 = new Ext.data.JsonStore({ fields: [{...}], .....}),
store2 = store1.clone(false); //just make a structural copy

store1.load({ //load them all here
params : {....},
callback : function(recs, options, success){
if(success){

this.suspendEvents(true);
store2.data = this.queryBy(
function(rec, id){ return !rec.isWhatIWant ; }
);
this.filterBy( function(rec, id){ return rec.isWhatIWant; } );
store2.fireEvent('datachanged', store2);
this.resumeEvents();

}
}
});


Swap out the filterBy with filter instead if your needs are simpler than shown.

Several ways to do it, but this uses straight Store methods to get you close. Tweak it. ;)

Condor
15 Jul 2010, 6:10 AM
Can't your server just return 2 separate roots in the data?

In that case you can simply use:

store1.load({
callback: function(){
store2.loadData(store1.reader.jsonData);
}
});
(with each store having a reader with a different root)

geewhizbang
15 Jul 2010, 6:33 AM
I ended up answering this myself some time ago. Condor's solution is really simple and elegant. I ended up with a functions that requested up to three different data items needed by the view, but only made one trip to the server.

rmd
15 Jul 2010, 9:15 PM
Can't your server just return 2 separate roots in the data?

In that case you can simply use:

store1.load({
callback: function(){
store2.loadData(store1.reader.jsonData);
}
});(with each store having a reader with a different root)


I can return 2 separate roots for a data. But the problem is on how to split the datastore according to its roots and load it to separate datastores. I understand what you're solution was trying to do but I'm not sure on how the reader should be created. Sorry about that, I'm just an Ext newbie.

Condor
15 Jul 2010, 10:21 PM
Example:

var store1 = new Ext.data.JsonStore({
url: 'myurl',
root: 'root1',
fields: ['field1', 'field2']
});
var store2 = new Ext.data.JsonStore({
url: 'myurl',
root: 'root2',
fields: ['field1', 'field2']
});
store1.load({
callback: function(){
store2.loadData(store1.reader.jsonData);
}
});
with data:

{
root1: [
{field1: 1, field2: 'One'},
{field1: 2, field2: 'Two'},
{field1: 3, field2: 'Three'}
],
root2: [
{field1: 4, field2: 'Four'},
{field1: 5, field2: 'Five'},
{field1: 6, field2: 'Six'}
]
}

rmd
15 Jul 2010, 10:33 PM
@Condor:

My main goal was to make an ajax call only once, and split a response into separate datastores according to its root. But I think your code will make a call twice. Is there a way to do that?

Animal
15 Jul 2010, 11:36 PM
Call twice?

Look at what he's suggesting!

One call to load TWO roots which are then fed into Store's loadData call.

Simples!

rmd
18 Jul 2010, 11:46 PM
Thanks for the help... and sorry about my latest comment, I was wrong.