Question

J'essaie d'implémenter un arbre de chargement différé entre domaines à l'aide de la boîte à outils Dojo. Jusqu'à présent, les nœuds de niveau supérieur s'affichent correctement, mais en cliquant sur expando, j'obtiens une erreur "différé a déjà été résolu" et je ne sais pas pourquoi. Je peux voir que la méthode fetch semble fonctionner en regardant l'onglet réseau Firebug. Je pense que mon problème est dans ma méthode _processResults, peut-être quelque chose à voir avec la définition du _loadObject qu'il contient ...

Je pense que je devrais mieux connaître Dojo étant donné tout le temps que j'ai passé à essayer de le comprendre. Mais hélas, c'est une vraie bête ... J'ai vu des mentions de JSONP et de lazyloading ne fonctionnant pas dans l'un des blogs sitepen ( http://www.sitepen.com/blog/2008/06/25/web-service-data-store/ ), mais il ne mentionne pas pourquoi cela ne devrait pas être possible autre que JSONP étant asyncronus. Si Dojo va simplement insérer des données json entrantes dans le magasin, je ne comprends pas pourquoi cela devrait avoir de l'importance.

Cela a peut-être à voir avec mon formatage des données - un autre exemple sur sitepen ( http://www.sitepen.com/blog/2010/01/27/effic-lazy-loading-of-a-tree/ ) en utilisant le jsonreststore ne charge pas un élément tant que vous ne développez pas un nœud, alors que mon format charge l'élément mais ne charge pas les nœuds enfants tant que vous ne le développez pas ...

Sans plus tarder, voici ta codez ...

<script type="text/javascript">
dojoConfig = {
parseOnLoad: true,
isDebug: true,
usePlainJson: true  
};
</script>
<script type="text/javascript" src="scripts/dojo_16/dojo/dojo.js"></script>

<script type="text/javascript">
    dojo.require("dojo.parser");
    dojo.require("dojo.io.script");
    dojo.require("dojox.rpc.Service");
    dojo.require("dojox.data.ServiceStore");                    
    dojo.require("dijit.tree.ForestStoreModel");                    
    dojo.require("dijit.Tree");         

    dojo.addOnLoad(function(){

        var mySmd = {
                "SMDVersion": "2.0",
                "id": "http://urlbehindfirewall/testtree/", 
                "description": "This is the service to get to the finder app backend data",

                transport: "JSONP",
                envelope: "URL",
                additionalParameters: true,
                target: "http://urlbehindfirewall/testtree/",               

                services: {
                    "getChildrenNodes": {
                    "target": "getChildrenNodes.php",
                        parameters: [
                            { name: "nodeId", type: "integer"}                             
                        ]
                    }
                }

        };

        var myService = new dojox.rpc.Service(mySmd);

        var myStoreParams = {               
            service : myService.getChildrenNodes,
            idAttribute : "Node_Id",
            labelAttribute : "Display_Name",
            _processResults: function(results, def){                                        
                var _thisStore = this;
                for(i in results){
                    results[i]._loadObject = function(callback){
                        _thisStore.fetch({
                        query: { nodeId: this.Node_Id },
                        onItem: callback
                        });
                    delete this._loadObject;
                    };
                }                   
                return {totalCount: results.length, items: results};                                                
            }
        };


        var myStore = new dojox.data.ServiceStore(myStoreParams);

        //create forestTreeModel
        var treeModelParams = {
            store: myStore,
            deferItemLoadingUntilExpand: true,
            childrenAttrs: ["Children_Nodes"],              
            rootId : 1,
            query: 1
            };

        var treeModel = new dijit.tree.ForestStoreModel(treeModelParams);

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

        dojo.byId("treeContainer").appendChild(myTree.domNode);
        myTree.startup();                   
    });

</script>

Et voici un exemple de la structure de données json: malheureusement, le service est actuellement derrière un pare-feu réseau ... je vais travailler sur la mise en place d'une version publique pour en faire la démonstration un peu. En attendant, voici la réponse pour la recherche sur le nœud racine, nœud 1:

    [
   {
      "Node_Id":"2",
      "Display_Name":"LeftNode:2",
      "Secondary_Names":"Parent:1",
      "Obi_Id":"10002",
      "Children_Nodes":[

      ],
      "Has_Children":true,
      "Child_Node_Ids":[
         "5",
         "6",
         "7",
         "8"
      ]
   },
   {
      "Node_Id":"3",
      "Display_Name":"Middle Node:3",
      "Secondary_Names":"Parent:1",
      "Obi_Id":"10003",
      "Children_Nodes":[

      ],
      "Has_Children":true,
      "Child_Node_Ids":[
         "9",
         "10"
      ]
   },
   {
      "Node_Id":"4",
      "Display_Name":"Right Node:4",
      "Secondary_Names":"Parent:1",
      "Obi_Id":"10004",
      "Children_Nodes":[

      ],
      "Has_Children":true,
      "Child_Node_Ids":[
         "11",
         "12"
      ]
   }
]

Le développement de l'un des nœuds ci-dessus obtiendrait alors les enfants de ce nœud - donc 2 obtiendrait le tableau de nœuds de 5,6,7,8. (Il n'est peut-être pas nécessaire d'avoir les Child_Node_Ids et Children_Nodes pour l'implémentation actuelle, mais ne devrait rien casser non?)

Je suis donc sûr que les yeux brillent maintenant, pour reformuler le problème - qu'est-ce qui crée cette erreur "différé a déjà été résolu"? Le chargement différé dans une arborescence est-il possible avec JSONP? Une structure json différente résoudrait-elle mes problèmes de chargement différé? Est-il possible de reformater mes données dans le dojo pour que cela fonctionne? (Je pensais que c'était le but de la méthode _processResults ...) Existe-t-il des services de données d'arborescence accessibles au public sur lesquels s'entraîner?

Merci à tous!

Était-ce utile?

La solution

Après beaucoup d'expérimentation et de frustration, voici mes conclusions:

Oui, le chargement paresseux d'un arbre est possible en utilisant JSONP. Oui, mettre mes données dans un format différent a aidé à résoudre le problème de chargement différé. J'ai trouvé un certain nombre de pierres d'achoppement en cours de route, que je mentionnerai plus tard.

Voici le code d'une implémentation fonctionnelle. D'abord le service:

<❯pretendService.php

$callback = $_GET["callback"];
$nodeName = $_GET["node"];
$fileName = "pretendServiceJson/".$nodeName.".js";

print($callback . "(" . file_get_contents($fileName) . ")" );

?>

pretendServiceJson / 0.js - ceci est la note initiale de chargement des données c'est un tableau!

[
{
   "Node_Id":"0",
   "Display_Name":"",
   "Children":[
      {
         "Node_Id":"1",
         "Display_Name":"node 1",
         "Obi_Id":"02",
         "Secondary_Names":"Blah blah secondary name node 1"
      },
      {
         "Node_Id":"2",
         "Display_Name":"node 2",
         "Obi_Id":"o2",
         "Secondary_Names":"Blah blah secondary name node 2"
      },
      {
         "$ref":"3",
         "Display_Name":"node 3",
         "Obi_Id":"o3",
         "Secondary_Names":"Blah blah secondary name node 3",
         "Children":true
      },
      {
         "Node_Id":"4",
         "Display_Name":"node 4",
         "Obi_Id":"o4",
         "Secondary_Names":"Blah blah secondary name node 4"
      },
      {
         "Node_Id":"5",
         "Display_Name":"node 5",
         "Obi_Id":"o5",
         "Secondary_Names":"Blah blah secondary name node 5"
      }
   ]
}
]

pretendServiceJson / 3.js - ce sera le premier élément chargé tardivement - notez c'est un objet !!!

{
    "Node_Id": "3",
    "Display_Name": "node 3",
    "Obi_Id": "o3",
    "Secondary_Names": "Blah blah secondary name node 3",
    "Children": [
        {
            "$ref": "6",
            "Display_Name": "node 6",
            "Obi_Id": "o6",
            "Secondary_Names": "Blah blah secondary name 06",
            "Children":true
        },
        {
            "Node_Id": "7",
            "Display_Name": "node 7",
            "Obi_Id": "o7",
            "Secondary_Names": "Blah blah secondary name 07"
        }
    ]
}

Il existe un autre fichier json 6.js mais je pense que vous avez compris. Enfin la magie ...

            dojo.require("dojo.parser");
        dojo.require("dojo.io.script");
        dojo.require("dojox.rpc.Service");
        dojo.require("dojox.data.JsonRestStore");                   
        dojo.require("dijit.tree.ForestStoreModel");                    
        dojo.require("dijit.Tree");         

        dojo.addOnLoad(function(){

            var mySmd = {
                    "SMDVersion": "2.0",
                    "id": "http://localhost/pretendService.php", 
                    "description": "This is the service to get to the finder app backend data",

                    transport: "JSONP",
                    envelope: "URL",
                    additionalParameters: true,
                    target: "http://localhost/",                

                    services: {
                        "getNode": {
                        "target": "pretendService.php",
                            parameters: [
                                { name: "node", type: "string"}                            
                            ]
                        }
                    }
            };

            var myService = new dojox.rpc.Service(mySmd);                       

            var myStore = new dojox.data.JsonRestStore({                
                service : myService.getNode,
                idAttribute : "Node_Id",
                labelAttribute : "Display_Name"             
            });     

            //create forestTreeModel
            var treeModelParams = {
                store: myStore,
                deferItemLoadingUntilExpand: true,
                childrenAttrs: ["Children"],                
                //rootId : "0",
                query: "0"
                };

            var treeModel = new dijit.tree.ForestStoreModel(treeModelParams);

            var myTree = new dijit.Tree({
                model: treeModel,
                id: "myTree",
                showRoot: false,
                persist: false
                });

            dojo.byId("treeContainer").appendChild(myTree.domNode);
            myTree.startup();

        });

    </script>
</head>

<body class="tundra">

<div id="treeContainer"></div>

</body>
</html>

La plus grande leçon ici est qu'il existe deux méthodes distinctes (du mieux que je suis capable de suivre) qui placent les données dans le magasin, puis dans l'arborescence. Le premier chargement de données proviendra d'une extraction, et il attendra un tableau d'éléments. Les éléments à chargement différé qui suivent (en supposant que vous avez correctement configuré le service et que vous obtenez des réponses) passeront par loadItem et cette méthode attendra un objet.

Si les données de chargement initiales arrivent en tant qu'objet, vous ne verrez aucune arborescence sur votre page, malgré la réponse dans firebug. Aucune erreur cependant.

Si les données chargées paresseusement arrivent sous forme de tableau, vous obtenez un "TypeError: args.item is undefined" - il semble que loadItem soit appelé 2x et la deuxième fois au lieu de votre objet résultat, c'est un objet vide.

/ p>

Si vous avez défini rootId lorsque vous créez le magasin, il n'affichera pas l'arborescence et vous donnera une erreur "Le nœud ne peut pas être inséré à la hiérarchie spécifiée".

Toutes les erreurs ci-dessus ont été trouvées en utilisant JsonRestStore. La documentation indique que JsonRestStore hérite de la fonctionnalité de lecture de ServiceStore, mais si je change les deux magasins, j'obtiens l'erreur «Le nœud ne peut pas être inséré à la hiérarchie spécifiée».

L'une de mes plus grandes frustrations avec Dojo est simplement le manque de documentation précisant comment les données réelles sont analysées avec succès en éléments pour les magasins de données. On parle beaucoup de la flexibilité et de la modularité des magasins de données, mais comment y faire entrer mes données et les faire fonctionner est toujours un mystère, et cette solution m'est venue comme je l'ai saisi à la paille. J'aimerais avoir un article sur le site Web sur la façon dont les données deviennent un jour des éléments de banque de données ...? :)

J'espère que cela aidera quelqu'un d'autre. Bon codage.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top