Moving nodes within a Dijit Tree

[亡魂溺海] 提交于 2019-12-25 09:19:52

问题


I am using a tree as an input tool to allow the user to organize categories.

I would like the users to be able to move the nodes around at the top level, specifically reordering them under the same parent.

Everything looks fine until it is time for the store to be updated - the display is wrong - the moved item is not shown in the right place.

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 - I could invest more time in this, but I don't want to. Choosing a different approach - using traditional inputs and providing a read-only tree view.


回答1:


You need to place the aspect around the store's put function before wrapping it with Observable. With your code Observable hasn't got access to the replaced put function. It will work if you replicate closely the example.

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


});

A fork of your JSFiddle.

UPDATE: The above solution does not support the betweenThreshold option (the ability to drop an item in between others instead of making it a child of another item). Even the official reference guide example does not work. This needs a store that properly supports positioning of items (MemoryStore doesn't and the hack for the put function is not enough). One option is to fall back on the deprecated 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();


});

Here is another JSFiddle. You can also refer to this example.



来源:https://stackoverflow.com/questions/40066310/moving-nodes-within-a-dijit-tree

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!