我在使用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中看不到任何错误消息。 我只是在页面上看到根“主题”。 感谢任何人都能以某种方式提供帮助。
答案 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
树需要五个模型方法来将数据呈现为树:
RestStore
- 已经由商店提供,通常不需要重新实现。getIdentity(object)
- 指示对象是否可能有子节点(在实际加载子节点之前)。在这个例子中,我们将“儿童”财产的存在视为生孩子的指示。mayHaveChildren(object)
- 要求检索孩子。这可以异步执行,并在完成时调用onComplete回调。在这个例子中,我们将执行get()来检索父对象的完整表示以获取子对象。一旦父完全加载,我们将从父级返回“children”数组。getChildren(parent, onComplete, onError)
- 被调用以检索根节点。应使用根对象调用onItem回调。在这个例子中,我们得到()具有根对象的“root”的id / URL的对象。getRoot(onItem)
- 返回对象的标签(这是树中节点旁边显示的文本)。在此示例中,标签只是对象的“名称”属性。那怎么可能呢?让我们做几个定义:
1)服务器设置getLabel(object)
'base',ID'root'和 2)服务器返回'children'密钥,如果有的话,则为true / p>
jsonrest.target
我们使用上面定义的变量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;
}
});
从我们的子数组中删除大部分数据,可以减少发送的有效负载,并可以利用延迟加载。对于收到的每一件物品(例如/ data / parents / number1parent),必须填写物品本身的完整表示。如果他/她有孩子,我们需要1)为var tree = new dijit.Tree({
model : treeModel
}, 'treeNode');
tree.startup();
中的labels
命名{1}} - 我们使用'name'键,参见getLabel方法,2)提供唯一ID,3)表明他们是否有孩子。
view
有了这个,我们将显示
ROOT
+ Pippo
*冥王星
+ Paperino
如果我们想点击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。然而,孩子们仍然是一个“短形代表对象”。
因此,为了论证,下面是一个如何用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