Dojo JsonRest商店和dijit.Tree

时间:2012-05-31 08:30:06

标签: json rest dojo 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>

我的休息服务响应以下json

{
data: [
{
"id": "PippoId",
"name": "Pippo",
"children": []
},
{
"id": "PlutoId",
"name": "Pluto",
"children": []
},
{
"id": "PaperinoId",
"name": "Paperino",
"children": []
}
]}

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

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

两者都没有。 我在firebug中看不到任何错误消息。 我只是在页面上看到根“主题”。 感谢任何人都能以某种方式提供帮助。

1 个答案:

答案 0 :(得分:14)

快速浏览一下;

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

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

尝试删除数据键:

[
  {
    "id": "PippoId",
    "name": "Pippo",
    "children": []
  }, {
    "id": "PlutoId",
    "name": "Pluto",
    "children": []
  }, {
    "id": "PaperinoId",
    "name": "Paperino",
    "children": []
  }
]

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

view

中缺少逻辑

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

  1. RestStore - 已经由商店提供,通常不需要重新实现。
  2. getIdentity(object) - 指示对象是否可能有子节点(在实际加载子节点之前)。在这个例子中,我们将“儿童”财产的存在视为生孩子的指示。
  3. mayHaveChildren(object) - 要求检索孩子。这可以异步执行,并在完成时调用onComplete回调。在这个例子中,我们将执行get()来检索父对象的完整表示以获取子对象。一旦父完全加载,我们将从父级返回“children”数组。
  4. getChildren(parent, onComplete, onError) - 被调用以检索根节点。应使用根对象调用onItem回调。在这个例子中,我们得到()具有根对象的“root”的id / URL的对象。
  5. getRoot(onItem) - 返回对象的标签(这是树中节点旁边显示的文本)。在此示例中,标签只是对象的“名称”属性。
  6. 那怎么可能呢?让我们做几个定义:
    1)服务器设置getLabel(object)'base',ID'root'和 2)服务器返回'children'密钥,如果有的话,则为true / p>

    jsonrest.target

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

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

    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;
        }
    });
    

    Serverside延迟加载JSON数据设置

    从我们的子数组中删除大部分数据,可以减少发送的有效负载,并可以利用延迟加载。对于收到的每一件物品(例如/ data / parents / number1parent),必须填写物品本身的完整表示。如果他/她有孩子,我们需要1)为var tree = new dijit.Tree({ model : treeModel }, 'treeNode'); tree.startup(); 中的labels命名{1}} - 我们使用'name'键,参见getLabel方法,2)提供唯一ID,3)表明他们是否有孩子。

    根JSON

    view

    有了这个,我们将显示
    ROOT
     + Pippo
     *冥王星
     + Paperino

    任何项目JSON

    如果我们想点击Pippo看他的孩子的物体,让我们倒退;树请求目标{ "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 } ] } ,它在RestStore中设计转换为对object.id == PippoId的请求 - 并且将使用treeNode.item.children shcema编译URL。在这种情况下,服务器将通过GET以完整的最终URL this.target/object.parent-relations/object.id进行响应。

    data/PippoID

    注意,'完整表示对象' - 顶级 - 有额外的实体,例如shoosize和surname。然而,孩子们仍然是一个“短形代表对象”。

    Serverside PHP Rest实现

    因此,为了论证,下面是一个如何用PHP实现其余功能的表示。我们将假设papparazies是sql-db中的一个表,并且实现{ "name": "Pippo", "id": "PippoId", "surname" : "foo", "shoosize" : "bar", "children": [ { "name": "Baz", "id": "BazId" }, { "name": "Godfather", "id": "GodfatherId", "children": true } ] } getPaparazi($id)函数来检索数据列。

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

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

    getPapasKids($id)

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

    <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>
    

    有关reststores和树的编译信息,请参阅SitePen blog