Timothy R. Butler
Timothy R. Butler

Reputation: 1139

Using Dijit.Tree with QueryReadStore for Lazy Loading

I'm trying to use dojox.data.QueryReadStore as the store for a lazy loading dijit.tree. I seem hard pressed to find examples of people using this store instead of JsonRestStore, but I would really like to stick to using query strings as opposed to REST syntax for the sake of consistency throughout my application. The trouble is, while I can get QueryReadStore to pass along the root level of the tree, lazy loading the children, it always fails.

Here's what I have:

        dojo.require("dojox.data.QueryReadStore");
        dojo.require("dijit.Tree");



        dojo.addOnLoad(function() {
            var store = new dojox.data.QueryReadStore({
                url:'/cgi-bin/safari/safari_json_responder.pl',
                requestMethod: "get"
            });

            var treeModel = new dijit.tree.ForestStoreModel({
                store: store,
                deferItemLoadingUntilExpand: true,
                query: { 'id' : "0" },
                childrenAttrs: ["children"]
            });

            var myTree = new dijit.Tree({
                model: treeModel
            },
            "treeOne");

            myTree.startup();

        });

When I click to expand one of the categories that has children, I get this error from Firebug:

Node cannot be inserted at the specified point in the hierarchy" code: "3 [Break On This Error] (function(){var _1=null;if((_1||(typeo...setTimeout(dojo._loadInit,100);}})();

Any suggestions on what might be the issue? You can see the live test page here:

http://asisaid.com/safari-resources/lazyLoad.html

Updated observations 19-Jun-2011:

I noticed isItemLoaded appears to claim to be incomplete in QueryReadStore. Perhaps the Dojo documentation saying QueryReadStore can handle lazy loading is incorrect? I've been trying to replace the QueryReadStore.isItemLoaded method, but haven't been able to figure out what it should do. I tried looking for the attribute "$ref" or "_reference," but that doesn't seem to be working.

Clearly, I am doing something wrong. Although somehow I feel like I'm on the right track. If I could notify the model that an item isn't entirely loaded, perhaps things would spring into action as they should (and do with JsonRestStore).

Here's what the data being output looks like right now when id=0 is passed to the server:

{"label":"name","identification":"id","items":[{"name":"Autobiographical","poid":"0","id":"3"},{"name":"Blogging","poid":"0","children":[{"name":"asisaid","id":"2","$ref":"2"},{"name":"blogware","id":"4","$ref":"4"}],"id":"1","$ref":"1"}, [...]

(truncated off to keep it from being too long.)

I've thrown references and data here and there trying different things (I'm sure I have too many in this example, but I've been trying to throw everything and see what sticks).

It originally looked like this for id=0:

{"label":"name","identification":"id","items":[{"name":"Autobiographical","poid":"0","id":"3"},{"name":"Blogging","poid":"0","children": "true","id":"1","$ref":"1"}, [...]

I also tried this:

{"label":"name","identification":"id","items":[{"name":"Autobiographical","poid":"0","id":"3"},{"name":"Blogging","poid":"0","children": [{"$ref":"2" },{"$ref":"4"}],"id":"1"}, [...]

None of these ideas (nor the same thing, but using "_reference" instead of "$ref" seems to do the trick.

Upvotes: 1

Views: 2274

Answers (1)

Gustavo Giráldez
Gustavo Giráldez

Reputation: 2690

EDIT: Forget about the references. You still have the problem described with the children attribute, but from looking at the source code for QueryReadStore and TreeStoreModel I don't see how it can ever work, at least in version 1.6. Also, see http://bugs.dojotoolkit.org/ticket/5876 . It says there that you don't need references, and you can pass id values directly. But again, I'm not sure it'll work. You may need to subclass and override some methods from QueryReadStore.


Your server script is returning an invalid value for the children attribute. It's returning true when it should return a list of references to other items, or the items themselves. Since in your case, you want to defer loading child items until expansion, the children attribute should have references. See this page in the Dojo reference guide.

Something like:

{
  "label":"name",
  "identification":"id",
  "items":[
    {
      "id":3,
      "name":"Autobiographical"
    },
    {
      "id":1,
      "name":"Blogging",
      "children": [
        {_reference:100}, {_reference:101}
      ]
    },
    ...
  ]
}

Where ids 100 and 101 and not necessarily returned in the first batch of data, but can be fetched later, by performing new queries to your server.

Also, the query in the ForestTreeModel should be something that returns your root items. {id:0} is not such a condition. You can add a dummy attribute root to all the returned items and set it to true for your roots. While {id:0} seems to work now, it might bite you later when the tree needs to requery the root items and the store uses the already loaded data.

Upvotes: 1

Related Questions