Dojo JsonRest商店和dijit.Tree

use*_*712 3 rest dojo json lazy-loading dijit.tree

我在使用ForestModel制作JSonRest存储和dijit.Tree时遇到了一些问题.我已经尝试了一些JsonRestStore和json数据格式的组合,遵循Web上的许多提示,但没有成功.

最后,在此处以示例形式 http://blog.respondify.se/2011/09/using-dijit-tree-with-the-new-dojo-object-store/

我编写了这个简单的页面(我正在使用dojotolkit 1.7.2)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Tree Model Explorer</title>

<script type="text/javascript">
djConfig = {
parseOnLoad : true,
isDebug : true,
}
</script>
<script type="text/javascript" djConfig="parseOnLoad: true"
src="lib/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.Tree");
dojo.require("dojo.store.JsonRest");
dojo.require("dojo.data.ObjectStore");
dojo.require("dijit.tree.ForestStoreModel");

dojo.addOnLoad(function() {

var objectStore = new dojo.store.JsonRest({
target : "test.json",
labelAttribute : "name",
idAttribute: "id"
});

var dataStore = new dojo.data.ObjectStore({

objectStore : objectStore
});

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

var tree = new dijit.Tree({
model : treeModel
}, 'treeNode');
tree.startup();
});
</script>
</head>
<body>

<div id="treeNode"></div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

我的休息服务响应以下json

{
data: [
{
"id": "PippoId",
"name": "Pippo",
"children": []
},
{
"id": "PlutoId",
"name": "Pluto",
"children": []
},
{
"id": "PaperinoId",
"name": "Paperino",
"children": []
}
]}
Run Code Online (Sandbox Code Playgroud)

我也尝试过以下响应(实际上我最后的意图是使用树的延迟加载)

{ data: [
 {
  "id": "PippoId",
  "name": "Pippo",
  "$ref": "author0",
  "children": true
 },
 {
  "id": "PlutoId",
  "name": "Pluto",
  "$ref": "author1",
  "children": true
 },
 {
  "id": "PaperinoId",
  "name": "Paperino",
  "$ref": "author2",
  "children": true
 }
]}
Run Code Online (Sandbox Code Playgroud)

这两部作品都没有.我在firebug中看不到任何错误消息.我只是在页面上看到根"主题".感谢任何人都可以在某种程度上提供帮助.

msc*_*chr 14

快速浏览一下;

您的服务器端返回错误的数据.这是来自dojo参考指南的快速启动 jsonrest,遵循GET部分.

不同之处在于,由于REST请求的外观(从浏览器获取GET)的方式,服务器端应该1)返回一个项目数组或2)返回一个项目.

请尝试删除数据密钥:

[
  {
    "id": "PippoId",
    "name": "Pippo",
    "children": []
  }, {
    "id": "PlutoId",
    "name": "Pluto",
    "children": []
  }, {
    "id": "PaperinoId",
    "name": "Paperino",
    "children": []
  }
]
Run Code Online (Sandbox Code Playgroud)

那么这不会带来懒惰的装载能力吗?这必须是因为模型在您的代码示例中具有相当复杂的设置,首先是REST store然后是OBJECT another store,然后是ForestTree model,最后是树view.实现模型为我们的商店提供的内容相当简单,并且允许跳过双重商店定义.否则,objectstore.query将调用reststore.query - 我不完全肯定会工作.

缺少逻辑 RestStore

树需要五种模型方法来将数据呈现为树:

  1. getIdentity(object) - 已经由商店提供,通常不需要重新实现.
  2. mayHaveChildren(object) - 指示对象是否可能有子节点(在实际加载子节点之前).在这个例子中,我们将"儿童"财产的存在视为生孩子的标志.
  3. getChildren(parent, onComplete, onError) - 打电话来找回孩子们.这可以异步执行,并在完成时调用onComplete回调.在这个例子中,我们将执行get()来检索父对象的完整表示以获取子对象.父完全加载后,我们从父级返回"children"数组.
  4. getRoot(onItem) - 调用以检索根节点.应使用根对象调用onItem回调.在这个例子中,我们得到()具有根对象的"root"的id/URL的对象.
  5. getLabel(object) - 返回对象的标签(这是树中节点旁边显示的文本).在此示例中,标签只是对象的"名称"属性.

那怎么可能呢?让我们做几个定义:
1)jsonrest.target 'base'的服务器集,ID'root '和 2)服务器返回'children'键总是如此,如果有的话,则为true

var reststore = JsonRest({
    target:"data/",         // << adapt URL
    mayHaveChildren: function(object){
        // if true, we might be missing the data, false and nothing should be done
        return "children" in object;
    },
    getChildren: function(object, onComplete, onError){
        // this.get calls 'mayHaveChildren' and if this returns true, it will load whats needed, overwriting the 'true' into '{ item }'
        this.get(object.id).then(function(fullObject){
            // copy to the original object so it has the children array as well.
            object.children = fullObject.children;
            // now that full object, we should have an array of children
            onComplete(fullObject.children);
        }, function(error){
            // an error occurred, log it, and indicate no children
            console.error(error);
            onComplete([]);
        });
    },
    getRoot: function(onItem, onError){
        // get the root object, we will do a get() and callback the result
        this.get("root").then(onItem, onError);
    },
    getLabel: function(object){
        // just get the name (note some models makes use of 'labelAttr' as opposed to simply returning the key 'name')
        return object.name;
    }
});
Run Code Online (Sandbox Code Playgroud)

使用自定义RestStore创建树作为模型

我们使用上面定义的变量reststore - 并简单地将其设置为树构造参数的模型

var tree = new dijit.Tree({
  model : treeModel
}, 'treeNode');
tree.startup();
Run Code Online (Sandbox Code Playgroud)

Serverside延迟加载JSON数据设置

省去我们的子数组中的大部分数据,可以减少发送的有效负载,并且可以利用延迟加载.对于每一个项目接收(例如/数据/父母/ number1parent)本身必须填写该项目的完整表示如果他/她有孩子,我们需要1)命名这些用于获取labelsview-我们使用"名" key,参见getLabel方法,2)提供唯一ID,3)表明他们是否有孩子.

根JSON

{
    "name": "Papparazis",
    "id": "root",
    "children": [
  {
    "id": "PippoId",
    "name": "Pippo",
    // may have children - makes dijit.Tree create expandoNode and events
    "children": true
  }, {
    // example leaf, children == undefined
    "id": "PlutoId",
    "name": "Pluto" 
  }, {
    "id": "PaperinoId",
    "name": "Paperino",
    "children": true
  }
]
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我们将展示
ROOT
+ Pippo
*Pluto
+ Paperino

任何项目JSON

如果我们想点击Pippo看他的孩子的物体,让我们倒退; 树请求目标treeNode.item.children,其中RestStore中的设计转换为对object.id == PippoId的请求 - 并且将使用this.target/object.parent-relations/object.idshcema 编译URL .在这种情况下,服务器将data/PippoID通过GET 以完整的最终URL表示进行响应.

{
    "name": "Pippo",
    "id": "PippoId",
    "surname" : "foo",
    "shoosize" : "bar",
    "children": [
        {
            "name": "Baz",
            "id": "BazId"
        }, {
            "name": "Godfather",
            "id": "GodfatherId",
            "children": true
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

请注意,"完整表示对象" - 顶级 - 具有额外的实体,例如shoosize和surname.然而,孩子们仍然是一个"短型代表对象".

Serverside PHP Rest实现

因此,为了论证,下面是一个如何用PHP实现其余功能的表示.我们会去的假设下,即papparazies是SQL-DB一张桌子和一个getPaparazi($id)沿getPapasKids($id)功能实现检索数据的列.

首先,我们需要告诉apache如何通过.htaccess修改来处理这个问题.如果您是新手,请查看以下资源:

把它放在/.htaccess中,其中'/'是你的DocumentRoot - 并将RewriteBase修改为nescessary

<IfModule mod_rewrite.c>
  RewriteEngine on
  # If your site is running in a VirtualDocumentRoot at http://example.com/,
  # uncomment the following line:
  # RewriteBase /
  # If no file nor a directory exists for the request url,
  # rewrite URLs of the form 'data/object' to the form 'index.php?rest=data/object'.

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?rest=$1 [L,QSA]

</IfModule>
Run Code Online (Sandbox Code Playgroud)

从index.php中的PHP角度(所有非现有文件请求的重写处理程序),我们可以简单地创建以下内容:

<?php

 if(isset($_REQUEST['rest'])) {

   // IMPORTANT; validate the request, e.g. check for referrer or similar

   $ids = explode("/", $_REQUEST['rest']);
   $pathCount = count($ids);
   $table = array_shift($ids); // as string, 'data/' by example
   if(!$table || $table == "") exit; //  ... validate more
   if($pathCount > 1) {
      $objectRequested = array_pop($ids); // as string '' for root
   }
   if($pathCount > 2) {
      $mid = $ids; // an array, holding rest of the path (middle relatives)
   }
   // with this in hand, we should be able to get the object. 
   // by example we're serving store data for paparazies which 
   // has the 'target' parameter set to 'data/'
   if($table == "data") {
      $fields = getPaparazi($objectRequested);
      $obj = new stdobject();
      $obj->name = $fields['name'];
      $obj->id = $objectRequested;
      $obj->shoosize = $fields['shoosize'];
      $obj->children = array();
      if( ( $children = getPapasKids($objectRequested) ) ) {
          foreach($children as $child) {
             $c_obj = new stdobject();
             $c_obj->name = $child['name'];
             $c_obj->id = $child['id'];
             if($child['hasChildren']) 
                $c_obj->children = true;
             $obj->children[] = $c_obj;
          }
      }
      header("Content-Type: application/x-json; charset=XXXXX");
      print json_encode($obj);
      flush();
      exit;
   }
 }
?>
Run Code Online (Sandbox Code Playgroud)

有关reststores和树的已编译信息,请参阅SitePen博客