PDA

View Full Version : JsonStore read data from local object (instead of fetching from a URL)



vince_cole
2 Dec 2013, 4:57 AM
Hello. This is for ExtJs 3.

I would like to make my JsonStore read its JSON data from an object (array of Ext.data.Record) instead of a URL. Is this possible? My code (below) doesn't work. I get the following error in firebug:

TypeError: root is undefined
var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
this^ line is in Ext.data.JsonReader.readRecords

Background:
The array of records is populated by copying records from 2 other stores (each of these stores populates itself in the usual way, by fetching data from a URL).

Code:

MyGridClass = Ext.extend( myGridBase, {

constructor : function ( config ) {

// base ctor creates this.store (a JsonStore, with config.url = null)
MyGridClass.superclass.constructor.call( this, config );

// reduce confusion wrt context below
var gridStore = this.store;

// define 2 'sub' stores, which each fetch data from their own URL
var substores =
[
new Ext.data.JsonStore({
url: config.dataUrls.MYGRID_DATA_URL_0
,root: config.dataRoot
,id: config.dataIdField
,fields: config.dataFields
,autoLoad: false
})
,new Ext.data.JsonStore({
url: config.dataUrls.MYGRID_DATA_URL_1
,root: config.dataRoot
,id: config.dataIdField
,fields: config.dataFields
,autoLoad: false
})
];


// be able to tell when the data is loaded
Ext.each( substores, function( substore ) {
substore.on( 'beforeload', function() {
this.isLoading = true;
return true;
});
substore.on( 'load', function() {
this.isLoading = false;
});
})


// make the main store load its data via the substores instead of its URL
gridStore.load = function()
{
// invoke the substores' load methods
Ext.each( substores, function( substore ){ substore.load(); } )

// wait for both stores to load, then load their data into this store
var waiting;
var waitAndLoad = function( n )
{
n = n ? n : 0;

if( waiting )
clearTimeout( waiting );


if( (substores[0].isLoading || substores[1].isLoading) && (n<10) )
waiting = setTimeout( function(){waitAndLoad(n+1)}, 1000 );
else
loadDataFromSubstores();
}
waitAndLoad();
}

// copy all the records from the substores into the main store
var loadDataFromSubstores = function()
{
var theData = [];


Ext.each( substores, function( substore ) {
substore.each( function( record ) {
var newRecord = record.copy();
Ext.data.Record.id( newRecord );
theData.push( newRecord );
});
});

gridStore.loadData( theData );
}

}

});



FWIW, here is the Stack Trace.
It looks like the problem is only happening because the main store is trying to fetch data from the URL. Can't I just bypass that, and have it fetch the data directly from an object instead???
readRecords(o=Object { info=[1], list=[2]})ext-al...g_33.js (line 25347)
read(response=Object { tId=35, status=200, statusText="OK", more...})ext-al...g_33.js (line 25299)
onRead(action="read", o=Object { request={...}, reader={...}, scope={...}, more...}, response=Object { tId=35, status=200, statusText="OK", more...})ext-al...g_33.js (line 25055)
createCallback(o=Object { request={...}, reader={...}, scope={...}, more...}, success=true, response=Object { tId=35, status=200, statusText="OK", more...})ext-al...g_33.js (line 25044)
handleResponse(response=Object { tId=35, status=200, statusText="OK", more...})ext-al...g_33.js (line 4064)
handleTransactionResponse(o=Object { conn=XMLHttpRequest, tId=35}, callback=Object { scope={...}, argument={...}, timeout=10800000}, isAbort=undefined, isTimeout=undefined)ext-ba...g_33.js (line 1864)
checkResponse(o=Object { conn=XMLHttpRequest, tId=35}, callback=Object { scope={...}, argument={...}, timeout=10800000}, conn=XMLHttpRequest { readyState=4, timeout=0, withCredentials=false, more...}, tId=35, poll=Object { 31=550, 34=650, 0=null, more...}, cbTimeout=10800000)ext-ba...g_33.js (line 1912)
below var args = arguments, method = this; return function()ext-ba...g_33.js (line 902)

willigogs
2 Dec 2013, 5:59 AM
If all stores consume the same data, then load the data via URL in the normal way for the first store - then in the store's load listener, grab the data and load it into the other stores by using the loadData() function.

e.g.


var store1 = new Ext.data.JsonStore({
// CONFIGS HERE
listeners: {
load: function(thisStore, records, options) {
var data = thisStore.reader.jsonData;
store2.loadData(data)
store3.loadData(data)
}
}
})

vince_cole
2 Dec 2013, 6:57 AM
OK, this looks like a good idea.The stores consume similar data (it has the same fields). I want my grid to display a combination of the records from 2 different URLs.I guess I just need my main store (connected to one the URLs) and one extra store (for the other URL).Then what I need to do is catch my main store's load event and in the handler: invoke the extra store's load method, wait for it to load, and then append everything from that store into my main store ... *before* returning from the main store's load handler. Something like this, maybe?


var store1 = new Ext.data.JsonStore({
// CONFIGS HERE
listeners: {
beforeload: function(thisStore) {
store2.load();
}

,load: function(thisStore, records, options) {
while( store2.isLoading ) { /* do nothing until store2 has appended its data into here */ }
}
}
});

var store2 = new Ext.data.JsonStore({
// CONFIGS HERE
listeners: {
beforeload: function(thisStore) {
thisStore.isLoading = true;
}
,load: function(thisStore, records, options) {
store1.loadData( thisStore.reader.jsonData, true ); // append my data into store1

thisStore.isLoading = false;
}
}
});

vince_cole
3 Dec 2013, 2:08 PM
http://www.sencha.com/forum/showthread.php?277108-how-to-combine-results-from-2-different-URLs-into-a-single-store&p=1015534#post1015534 (http://RESOLVED: http://www.sencha.com/forum/showthread.php?277108-how-to-combine-results-from-2-different-URLs-into-a-single-store&p=1015534#post1015534)