Items can be handled in chunks, as well as streamed in. The other articles about datastores show items as a flat list with no hierarchy. So, what if you want a datastore to represent hierarchical data? And how do you walk across the hierarchy? Walking the hierarchy is, in fact, quite easy to do. The following example shows how to do this using JsonItemStore.
Assume a datasource of:
{ identifier: 'name',
label: 'name',
items: [
{ name:'Africa', type:'continent',
children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
{ name:'Egypt', type:'country' },
{ name:'Kenya', type:'country',
children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
{ name:'Nairobi', type:'city' },
{ name:'Mombasa', type:'city' },
{ name:'Sudan', type:'country',
children:{_reference:'Khartoum'} },
{ name:'Khartoum', type:'city' },
{ name:'Asia', type:'continent',
children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
{ name:'China', type:'country' },
{ name:'India', type:'country' },
{ name:'Russia', type:'country' },
{ name:'Mongolia', type:'country' },
{ name:'Australia', type:'continent', population:'21 million',
children:{_reference:'Commonwealth of Australia'}},
{ name:'Commonwealth of Australia', type:'country', population:'21 million'},
{ name:'Europe', type:'continent',
children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
{ name:'Germany', type:'country' },
{ name:'France', type:'country' },
{ name:'Spain', type:'country' },
{ name:'Italy', type:'country' },
{ name:'North America', type:'continent',
children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
{ name:'Mexico', type:'country', population:'108 million', area:'1,972,550 sq km',
children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
{ name:'Canada', type:'country', population:'33 million', area:'9,984,670 sq km',
children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
{ name:'United States of America', type:'country' },
{ name:'South America', type:'continent',
children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
{ name:'Brazil', type:'country', population:'186 million' },
{ name:'Argentina', type:'country', population:'40 million' }
]}
The above datasource for JsonItemStore uses references to other items to build the hierarchy. Other datasources and datastores might use different internal representations for hierarchy. But, in this example, notice that the continent type items have children that are countries, which in turn have children that are cities.
The following code snippet walks across this hierarchy and displays all country items contained by the continent items:
var store = new dojo.data.ItemFileReadStore({url: "countries.json"});
//Load completed function for walking across the attributes and child items of the
//located items.
var gotContinents = function(items, request){
//Cycle over all the matches.
for(var i = 0; i < items.length; i++){
var item = items[i];
//Cycle over all the attributes.
var attributes = store.getAttributes(item);
for (var j = 0; j < attributes.length; j++){
//Assume all attributes are multi-valued and loop over the values ...
var values = store.getValues(item, attributes[j]);
for(var k = 0; k < values.length; k++){
var value = values[k];
if(store.isItem(value)){
//Test to see if the items data is fully loaded or needs to be demand-loaded in (the item in question is just a stub).
if(store.isItemLoaded(value)){
console.log("Located a child item with label: [" + store.getLabel(value) + "]");
}else{
//Asynchronously load in the child item using the stub data to get the real data.
var lazyLoadComplete = function(item){
console.log("Lazy-Load of item complete. Located child item with label: [" + store.getLabel(item) + "]");
}
store.loadItem({item: value, onItem: lazyLoadComplete});
}
}else{
console.log("Attribute: [" + attributes[j] + "] has value: [" + value + "]");
}
}
}
}
}
//Call the fetch of the toplevel continent items.
store.fetch({query: {type: "continent"}, onComplete: gotContinents});
RUN in IE6.0 RESULT:
Attribute: [name] has value: [Africa]
Attribute: [type] has value: [continent]
Located a child item with label: [Egypt]
Located a child item with label: [Kenya]
Located a child item with label: [Sudan]
Attribute: [name] has value: [Asia]
Attribute: [type] has value: [continent]
Located a child item with label: [China]
Located a child item with label: [India]
Located a child item with label: [Russia]
Located a child item with label: [Mongolia]
Attribute: [name] has value: [Australia]
Attribute: [type] has value: [continent]
Attribute: [population] has value: [21 million]
Located a child item with label: [Commonwealth of Australia]
Attribute: [name] has value: [Europe]
Attribute: [type] has value: [continent]
Located a child item with label: [Germany]
Located a child item with label: [France]
Located a child item with label: [Spain]
Located a child item with label: [Italy]
Attribute: [name] has value: [North America]
Attribute: [type] has value: [continent]
Located a child item with label: [Mexico]
Located a child item with label: [Canada]
Located a child item with label: [United States of America]
Attribute: [name] has value: [South America]
Attribute: [type] has value: [continent]
Located a child item with label: [Brazil]
Located a child item with label: [Argentina]
Tests:
Note: The previous sample also demonstrates how lazy-loading (on-demand) of items can be done through the combination of the isItemLoaded() and loadItem() functions. For a demonstration of a lazy-loading approach that uses an extended version of ItemFileReadStore, see the demo in dojox/data/demos/demo_LazyLoad.html.