Domanda

Sto cercando di implementare un albero di caricamento trasversale, pigro usando il dojo toolkit. Finora ho i nodi di alto livello che vengono visualizzati correttamente, ma facendo clic sull'Enpanzione ricevo un errore "differito è già stato risolto" e non sono sicuro del perché. Vedo che il metodo Fetch sembra funzionare guardando la scheda Firebug Network. Penso che il mio problema sia nel mio metodo _processResults, forse qualcosa a che fare con la definizione di _loadObject al suo interno ...

Sento che dovrei conoscere Dojo meglio dato tutto il tempo che ho trascorso cercando di capirlo. Ma ahimè, è piuttosto una bestia ... Ho visto un po 'di menzione di JSONP e Lazyloading che non funziona in uno dei blog di Sitepen (http://www.sitepen.com/blog/2008/06/25/web-service-data-store/ ), ma non menziona il motivo per cui non dovrebbe essere possibile se non quello che JSONP è Asyncronus. Se Dojo sta per far sì che le cose JSON in arrivo nel negozio, non capisco perché dovrebbe importare.

Forse ha a che fare con la mia formazione dei dati - un altro esempio su Sitepen (http://www.sitepen.com/blog/2010/01/27/efficient-lazy-loading-of-a-tree/) Utilizzo di JSonreststore non carica un elemento fino a quando non si espande un nodo, mentre il mio formato carica l'articolo ma non carica i nodi per bambini fino a quando non lo espandi ...

Senza ulteriori indugi, ecco il 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>

Ed ecco un esempio della struttura dei dati JSON: purtroppo il servizio è dietro un firewall di rete attualmente ... Lavorerò per mettere una versione pubblica per dimostrare tra poco. Nel frattempo, questa è la risposta per la ricerca sul nodo radice, nodo 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"
      ]
   }
]

L'ampliamento di uno qualsiasi dei nodi di cui sopra otterrebbe quindi i figli di quel nodo - quindi 2 otterrebbe l'array di nodi di 5,6,7,8. (Potrebbe non essere necessario avere Child_node_ids e Children_nodes per l'attuale implementazione, ma non dovrebbe spezzare nulla no?)

Quindi sono sicuro che gli occhi sono ormai vetrati, per riaffermare il problema: cosa sta creando questo errore "differito è già stato risolto"? Il caricamento pigro in un albero è possibile con JSONP? Una struttura JSON diversa risolverebbe i miei pigri problemi di caricamento? È possibile riformattare i miei dati all'interno di Dojo in modo che funzioni? (Ho pensato che fosse il punto per il metodo _processResults ...) Ci sono servizi di dati degli alberi accessibili al pubblico per esercitarsi?

Grazie a tutti!

È stato utile?

Soluzione

Dopo molta sperimentazione e frustrazione sono le mie scoperte:

Sì, il caricamento pigro di un albero è possibile usando JSONP. Sì, mettere i miei dati in un formato diverso ha aiutato a risolvere il problema di caricamento pigro. Ho trovato un numero di blocchi inciampanti lungo la strada, che menzionerò più avanti.

Ecco il codice per un'implementazione funzionante. Prima il servizio:

pretenservice.php

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

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

?>

pretenservicejson/0.js - Questa è la nota di caricamento dei dati iniziali È un array!

[
{
   "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"
      }
   ]
}
]

pretenservicejson/3.js - Questo sarà il primo elemento caricato pigro - Nota è un oggetto !!!

{
    "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"
        }
    ]
}

C'è un altro file JSON 6.js ma penso che tu abbia il punto. Finalmente la magia ...

            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 lezione più grande qui è che ci sono due metodi separati (il meglio che sono in grado di seguire) che mettono i dati nel negozio e poi successivamente nell'albero. Il primo DataLoad arriverà da un recupero e si aspetterà una serie di articoli. Gli elementi carichi di pigro che seguono (supponendo che tu abbia configurato il servizio correttamente e stai ricevendo le risposte) passerà attraverso loadItem e quel metodo si aspetterà un oggetto.

Se hai i dati di caricamento iniziali in arrivo come oggetto, non vedrai alcun albero sulla tua pagina, nonostante vediamo la risposta in Firebug. Nessun errore però.

Se hai i dati caricati in modo pigro in arrivo come un array, ottieni un "typeerror: args.Item non è definito" - sembra che loadItem venga chiamato 2x e la seconda volta invece dell'oggetto di risultato è un oggetto vuoto.

Se hai definito rootid quando si crea l'archivio non visualizzerà l'albero e ti dà un errore "Il nodo non può essere inserito all'errore di gerarchia specificata".

Tutti gli errori di cui sopra sono stati trovati usando JSonreststore. La documentazione afferma che JSonreststore eredita la funzionalità di lettura di ServiceStore, ma se cambio i due negozi ottengo l'errore "Il nodo non può essere inserito alla gerarchia specificata".

Una delle mie più grandi frustrazioni con Dojo è semplicemente la mancanza di documentazione che specifica il modo in cui i dati effettivi vengono analizzati con successo negli articoli per i dati di dati. Si parla molto della flessibilità e della modularità dei negozi di dati, ma su come ottenere i miei dati lì dentro e farlo funzionare è ancora un mistero, e questa soluzione mi è arrivata mentre mi afferravo le cannucce. Mi piacerebbe avere un articolo di Sitepen su come un giorno i dati diventano elementi DataStore ...? :)

Spero che questo aiuti qualcun altro là fuori. Codice felice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top