the singularity of being and nothingness
Sencha: Creating Child Stores
One of the things I <3 about Sencha is the data store. They are super-simple to create, but very powerful for creating robust, data-driven applications. The other day, I found myself creating 3 data stores that were extremely similar, simply because of the fact that the data returned was fairly complex and nested. You see, with a Sencha store, you define a “root” of your data, which is really just how the store’s Reader will treat the “rows” of data that are fed into the store. This works very well, but in my scenario, I was wanting to create a master store of data defined at the highest possible root, and then create child stores based on some of the nested objects belonging to my initial data set. So in this case, instead of making 3 remote calls to get the same, but differently-structured data, I wanted to make 1 request and use the result 2 more times for different stores.
At first, I looked to the store itself for something like a “copy” or “clone” method, but there was none. There IS an option for doing an “each” loop for every record, but that just seemed a bit overkill. But then I took a step back and thought about a store’s data. When you get down to it, loading data into a store is not a magic process, nor is the format some mystical, obfuscated structure. The data is really only an object, and correlates precisely to what you define for the Store’s reader.
With this knowledge in hand, I tried the following:
var artiststore = new Ext.data.JsonStore({ storeId: "artiststore", url: "handler.cfm", baseParams: {method:"artistdetails",artistId:11525145}, root: "artist", fields: extartistfields.getRange(), listeners: { load:function(el,records){ artisttrackstore.loadData(records[0].json); artistalbumstore.loadData(records[0].json); } } });var artisttrackstore = new Ext.data.JsonStore({storeId:"artisttrackstore",root: "topTrack",fields: trackfields.getRange()}); var artistalbumstore = new Ext.data.JsonStore({ storeId:"artistalbumstore", root: "topAlbums", fields: albumfields.getRange() });
… and it worked brilliantly.
Nothing tremendously crazy happening here. First, I create a listener on my “parent” store for the “load” method (this fires AFTER data has been loaded into the store). Then, on the load method, I simply initiate a loadData() on each of my child stores, passing to them the object expected by their internal Reader (in this case, a json-formatted string). Then, to wrap things up, I simply define a new “root” on each child store, each corresponding to the nested object from the parent store that I wanted to drill down into.
Print article | This entry was posted by existdissolve on October 11, 2010 at 4:57 pm, and is filed under ExtJS. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |
about 14 years ago
Do you have an example of the JSON you were pulling from? I am having trouble getting your example to work for what I am doing.
about 14 years ago
Here’s the JSON response from the webservice that my app hits:
{
"artist":{
"@version":"1.1",
"id":12609970,
"name":"David Archuleta",
"topTrack":[
{
"trackName":"Joy To The World",
"playTrackURL":"http://api.napster.com:8080/rest/1.1/tracks/29833502?format=json&",
"explicit":false,"popularity":0,"duration":"04:19",
"artistName":"David Archuleta",
"artistResourceURL":"http://api.napster.com:8080/rest/1.1/artists/12609970?format=json&",
"albumName":"Christmas From The Heart",
"albumResourceURL":"http://api.napster.com:8080/rest/1.1/albums/13377911?format=json&"
},
{
...
},
],
"relatedArtists":[
{
"id":12243917,
"name":"Jordin Sparks",
"restArtistURL":"http://api.napster.com:8080/rest/1.1/artists/12243917?format=json&"
},
}
...
}
]
}
}
Hope this helps, and let me know if there’s anything I can do to help. Thanks!
about 14 years ago
Hmm…that output is awful. Here’s where you can find the full output: http://access.napster.com/docs/artist-details.html
about 13 years ago
But this won’t work with more than one item in the root 🙁 (e.g. article list with tags, kategories with articles inside, …) How can one implement that?!
about 13 years ago
I had a need like this recently and ended up putting the load logic in the child store. The reason is because sometimes I need to load the child store into a component, so I was forced to load the parent first which was awkward. So in the children stores, I did this:
//POPULATED BY CONFERENCES STORE FOR HOLDING SUBSET DATA
Ext.define(‘MyApp.store.Speakers’, {
extend: ‘Ext.data.Store’,
model: ‘MyApp.model.Speaker’,
autoLoad: true,
proxy: {
type: ‘memory’,
reader: {
type: ‘json’
}
},
listeners: {
beforeload: function(store, operation, options) {
var conferenceDetailsStore = Ext.getStore(‘ConferenceDetails’);
conferenceDetailsStore.load(function(records, operation, success) {
if (success) {
store.loadData(records[0].data.Speakers);
}
});
}
}
});
I think the real answer though is to create a store proxy that would read from a parent store. Check this thread out: http://www.sencha.com/forum/showthread.php?152057-Custom-proxy-to-read-from-another-store