我使用树作为输入工具来允许用户组织类别。
我希望用户能够在顶层移动节点,特别是在相同的父节点下重新排序它们。
一切看起来都很好,直到商店更新的时候——显示是错误的——移动的物品没有显示在正确的位置。
require([
"dojo/aspect",
"dojo/store/Memory",
"dojo/store/Observable",
"dijit/Tree",
"dijit/tree/ObjectStoreModel",
"dijit/tree/dndSource",
"dojo/domReady!"
], function(aspect, Memory, Observable, Tree, ObjectStoreModel, dndSource) {
var observableStore, model;
var memoryStore = new Memory({
data: [{
"id": 10,
"position": 0,
"name": "top",
"parent": null
}, {
"id": 19,
"position": 18,
"name": "Audio",
"parent": 10
}, {
"id": 23,
"position": 19,
"name": "Monitors",
"parent": 10
}, {
"id": 20,
"position": 20,
"name": "Communication",
"parent": 10
}, {
"id": 21,
"position": 28,
"name": "Video",
"parent": 10
}, {
"id": 18,
"position": 29,
"name": "Camera",
"parent": 10
}, {
"id": 22,
"position": 40,
"name": "Five",
"parent": 21
}, {
"id": 24,
"position": 60,
"name": "Networking",
"parent": 21
}, {
"id": 25,
"position": 70,
"name": "Toasters",
"parent": 18
}],
mayHaveChildren: function(object) {
var children = this.store.getChildren(object);
return children.length > 0;
},
getChildren: function (object) {
return this.query({parent: object.id});
}
});
observableStore = new Observable(memoryStore);
model = new ObjectStoreModel({
store: observableStore,
query: {
name: "top"
}
});
aspect.around(memoryStore, "put", function(originalPut) {
// To support DnD, the store must support put(child, {parent: parent}).
// Since memory store doesn't, we hack it.
// Since our store is relational, that just amounts to setting child.parent
// to the parent's id.
return function(obj, options) {
if (options && options.parent) {
obj.parent = options.parent.id;
}
return originalPut.call(memoryStore, obj, options);
}
});
var tree =new Tree({
model: model,
dndController: dndSource,
betweenThreshold: 5,
showRoot: false,
persist: false
}, "category-tree").startup();
});
JSFiddle
https://bugs.dojotoolkit.org/ticket/18142 -我可以花更多的时间在这上面,但我不想。选择一种不同的方法——使用传统的输入并提供只读的树视图。
在用Observable包装之前,你需要把aspect放在store的put函数周围。在你的代码中,Observable不能访问被替换的put函数。如果你仔细地复制这个例子,它就会起作用。
require([
"dojo/aspect",
"dojo/store/Memory",
"dojo/store/Observable",
"dijit/Tree",
"dijit/tree/ObjectStoreModel",
"dijit/tree/dndSource",
"dojo/domReady!"
], function(aspect, Memory, Observable, Tree, ObjectStoreModel, dndSource) {
var observableStore, model;
var memoryStore = new Memory({
data: [{
"id": 10,
"position": 0,
"name": "top",
"parent": null
}, {
"id": 19,
"position": 18,
"name": "Audio",
"parent": 10
}, {
"id": 23,
"position": 19,
"name": "Monitors",
"parent": 10
}, {
"id": 20,
"position": 20,
"name": "Communication",
"parent": 10
}, {
"id": 21,
"position": 28,
"name": "Video",
"parent": 10
}, {
"id": 18,
"position": 29,
"name": "Camera",
"parent": 10
}, {
"id": 22,
"position": 40,
"name": "Five",
"parent": 21
}, {
"id": 24,
"position": 60,
"name": "Networking",
"parent": 21
}, {
"id": 25,
"position": 70,
"name": "Toasters",
"parent": 18
}],
mayHaveChildren: function(object) {
var children = this.store.getChildren(object);
return children.length > 0;
},
getChildren: function (object) {
return this.query({parent: object.id});
}
});
aspect.around(memoryStore, "put", function(originalPut) {
// To support DnD, the store must support put(child, {parent: parent}).
// Since memory store doesn't, we hack it.
// Since our store is relational, that just amounts to setting child.parent
// to the parent's id.
return function(obj, options) {
if (options && options.parent) {
obj.parent = options.parent.id;
}
return originalPut.call(memoryStore, obj, options);
}
});
observableStore = new Observable(memoryStore);
model = new ObjectStoreModel({
store: observableStore,
query: {
name: "top"
}
});
var tree =new Tree({
model: model,
dndController: dndSource,
showRoot: false,
persist: false
}, "category-tree").startup();
});
JSFiddle的一个分支。
UPDATE:上面的解决方案不支持betweenThreshold选项(将一个项目放到其他项目之间,而不是使其成为另一个项目的子项目的能力)。甚至官方的参考指南示例也不起作用。这需要一个正确支持项定位的存储(MemoryStore不支持,并且对put函数的修改还不够)。一个选项是退回到已弃用的dojo/data/ItemFileWriteStore。
require([
"dojo/data/ItemFileWriteStore",
"dijit/Tree",
"dijit/tree/TreeStoreModel",
"dijit/tree/dndSource",
"dojo/domReady!"
], function(ItemFileWriteStore, Tree, TreeStoreModel, dndSource) {
var model;
var categories = {
identifier: 'id',
label: 'name',
items: [
{ id: '0', name:'Foods', numberOfItems:1, children:[ {_reference: '1'}, {_reference: '2'}, {_reference: '3'} ] },
{ id: '1', name:'Fruits', numberOfItems:1, children:[ {_reference: '4'} ] },
{ id: '4',name:'Citrus', numberOfItems:1, items:[ {_reference: '5'} ] },
{ id: '5', name:'Orange'},
{ id: '2', name:'Vegetables', numberOfItems:0},
{ id: '3', name:'Cereals', numberOfItems:0}
]
};
var memoryStore = new ItemFileWriteStore({data: categories});
var model = new TreeStoreModel({store: memoryStore, query:{id: "0"}});
var tree =new Tree({
model: model,
dndController: dndSource,
betweenThreshold: 5,
showRoot: false,
persist: false
}, "category-tree").startup();
});
这是另一个JSFiddle。你也可以参考这个例子