Pregunta

Estoy tratando de implementar un árbol de carga de dominio cruzado y perezoso utilizando el kit de herramientas Dojo. Hasta ahora tengo los nodos de nivel superior que se muestran correctamente, pero al hacer clic en el expirador, obtengo un error de "diferido ya se ha resuelto" y no estoy seguro de por qué. Puedo ver que el método de búsqueda parece estar funcionando mirando la pestaña Network Firebug. Creo que mi problema está dentro de mi método _processresults, tal vez algo que ver con la definición del _loadObject dentro de él ...

Siento que debería saber que el dojo mejor dado todo el tiempo que pasé tratando de entenderlo. Pero, por desgracia, es una gran bestia ... He visto alguna mención de JSONP y LazyLoading que no funcionan en uno de los blogs de SitePen (http://www.sitepen.com/blog/2008/06/25/web-service-data-store/ ), pero no menciona por qué no debería ser posible aparte de que JSONP sea Asyncronus. Si Dojo solo va a meter datos de JSON entrantes en la tienda, no entiendo por qué eso debería importar.

Quizás tenga que ver con mi formación de datos, otro ejemplo en Sitepen (http://www.sitepen.com/blog/2010/01/27/eficiente-lazy-loading-of-a-tee/) Uso del JSONRestStore no carga un elemento hasta que expanda un nodo, mientras que mi formato carga el elemento pero no carga los nodos de los niños hasta que lo expanda ...

Sin más preámbulos, aquí está 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>

Y aquí hay un ejemplo de la estructura de datos JSON: desafortunadamente, el servicio está detrás de un firewall de red actualmente ... Trabajaré para poner una versión pública para demostrar en un momento. Mientras tanto, esta es la respuesta para buscar en el nodo raíz, 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"
      ]
   }
]

Expandir cualquiera de los nodos anteriores obtendría a los niños de ese nodo, por lo que 2 obtendría la matriz de nodos de 5,6,7,8. (Puede que no sea necesario tener el child_node_ids y los niños_nodes para la implementación actual, pero no debería estar rompiendo nada, no?)

Así que estoy seguro de que los ojos se están acrustando por ahora, para reafirmar el problema: ¿qué está creando este error de "diferido ya se ha resuelto"? ¿Es posible cargar elzando en un árbol con JSONP? ¿Una estructura JSON diferente resolvería mis problemas de carga perezosos? ¿Es posible reformatear mis datos dentro de Dojo para que funcione? (Pensé que ese era el punto del método _processresults ...) ¿Hay algún servicio de datos de árboles de acceso público para practicar?

¡Gracias a todos!

¿Fue útil?

Solución

Después de mucha experimentación y frustración, estos son mis hallazgos:

Sí, la carga perezosa de un árbol es posible usando JSONP. Sí, poner mis datos en un formato diferente ayudó a resolver el problema de carga perezosa. Encontré una serie de obstáculos en el camino, que mencionaré más tarde.

Aquí está el código para una implementación de trabajo. Primero el servicio:

fingendervice.php

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

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

?>

PretendServiceJson/0.js - Esta es la nota de carga de datos inicial ¡Es una matriz!

[
{
   "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 - Este será el primer elemento cargado perezoso - Nota es un objeto !!!

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

Hay otro archivo JSON 6.js, pero creo que entiendes el 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 lección más importante aquí es que hay dos métodos separados (lo mejor que puedo seguir) que ponen los datos en la tienda, y luego posteriormente en el árbol. El primer DataLoad vendrá de una búsqueda, y esperará una variedad de elementos. Los elementos de carga perezosa que siguen (suponiendo que haya configurado el servicio correctamente y que esté recuperando las respuestas) pasarán por LoadItem y ese método esperará un objeto.

Si tiene los datos de carga iniciales como objeto, no verá ningún árbol en su página, a pesar de ver la respuesta en Firebug. Sin embargo, no hay errores.

Si tiene los datos cargados de perezoso que entran como una matriz, obtiene un "TypeError: Args.Item no está definido", parece que LoadItem se llama 2x y la segunda vez en lugar de su objeto de resultado es un objeto vacío.

Si tiene RootID definido cuando crea la tienda, no mostrará el árbol y le dará un error "no se puede insertar en el error de jerarquía especificada".

Todos los errores anteriores se encontraron usando JsonrestStore. La documentación dice que JSONRestStore hereda la funcionalidad de lectura de ServiceStore, pero si cambio las dos tiendas obtengo el error "El nodo no se puede insertar en la jerarquía especificada".

Una de mis mayores frustraciones con Dojo es simplemente la falta de documentación que especifique cómo los datos reales se analizan con éxito en los elementos para las tiendas de datos. Se habla mucho sobre la flexibilidad y la modularidad de las tiendas de datos, pero cómo poner mis datos allí y hacer que funcione sigue siendo un misterio, y esta solución se me ocurrió cuando me entendí de pajitas. Me encantaría tener un artículo de SitePen sobre cómo los datos se convierten en elementos de almacén de datos algún día ...? :)

Espero que esto ayude a alguien más. Feliz codificación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top