ItemFileReadStore and the hierarchical Parameter

One cunning trick in Dojo can be to use an ItemFileReadStore class (or its read-write brother, ItemFileWriteStore) to take a list of data, often from an array in memory, and provide the ability to sort it, retrieve certain ranges, and allow other forms of manipulation. Each element of the array is typically a JavaScript object. Each of the properties of the object maps to an attribute in datastore speak.

However, the store doesn’t always operate as you might expect if these attributes are in turn objects themselves. For example, let’s say you wrote some code like this:

// HTML ...
            dojo.require("dojo.data.ItemFileReadStore");

            dojo.addOnLoad(function() {
                var dataArray = [
                { name: "Fred",
                    phonenumbers: { home: "01234 567890",
                        mobile: "04321 098765" }},
                { name: "Dave",
                    phonenumbers: { home: "05678 567890",
                        mobile: "08765 098765" }}];

                var store = new dojo.data.ItemFileReadStore({"data":
                        {"items": dataArray},
                });

                var body = dojo.query(".body");

                var gotItem = function(item) {
                    var phonenumbers = store.getValue(item, "phonenumbers");
                    body.appendChild(document.createTextNode(dojo.toJson(phonenumbers)));
                };

                store.fetch({onItem: gotItem, scope:this});
            });
// HTML...

This won’t do what you likely expect. In fact, it will fail with an error. The object phonenumbers which is returned from the store contains a substantial amount of metadata about the store, and dojo.toJson will fail with a stack overflow when it tries to serialize it. This screen capture from Chrome’s debugger shows some of what the object looks like:

The trick is to set the hierarchical parameter on the constructor of the datastore to false, like this:

                var store = new dojo.data.ItemFileReadStore({"data":
                        {"items": dataArray},
                        "hierarchical": false,
                });

This tells the datastore you don’t want it to treat the data within the attributes as datastore attributes themselves, just as plain Javascript objects. Now, the phonenumbers object returned is simple, and can be serialized straightforwardly, so you should see this in your browser:

{"home":"01234 567890","mobile":"04321 098765"}{"home":"05678 567890","mobile":"08765 098765"}

Thanks to James Thomas for the help with this technique described in this post.