javascript 如何动态更新道场树数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5409097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 17:06:14  来源:igfitidea点击:

How to update dojo tree data dynamically

javascriptdojotree

提问by Zion

I would like to know how ot update the data of the dojo.dijit.tree component dynamically. At the moment I'm creating the tree using dojo.data.ItemFileReadStore and dijit.tree.ForestStoreModel. Once I create the tree, I would like to reload it periodically with new JSON data.

我想知道如何动态更新 dojo.dijit.tree 组件的数据。目前我正在使用 dojo.data.ItemFileReadStore 和 dijit.tree.ForestStoreModel 创建树。创建树后,我想定期使用新的 JSON 数据重新加载它。

This is how I create the tree at the moment:

这就是我目前创建树的方式:

<div dojoType="dojo.data.ItemFileReadStore" jsId="myStore" url=getJSONResult></div>

<div dojoType="dijit.tree.ForestStoreModel" jsId="myModel" store="myStore" query="{type:'cat'}" rootId="myRoot" rootLabel="Data" childrenAttrs="children"></div>

<div dojoType="dijit.Tree" model="myModel" labelAttr="sname" label="Data" />

Thanks in advance.

提前致谢。

回答by Layke

Explicitly you "can't", but that doesn't mean you can't hack things to pieces and die trying.

明确地说你“不能”,但这并不意味着你不能把东西拆成碎片并尝试死。

refreshTree : function(){
    dijit.byId("myTree").dndController.selectNone(); // As per the answer below     
    // Credit to this discussion: http://mail.dojotoolkit.org/pipermail/dojo-interest/2010-April/045180.html
    // Close the store (So that the store will do a new fetch()).
    dijit.byId("myTree").model.store.clearOnClose = true;
    dijit.byId("myTree").model.store.close();

    // Completely delete every node from the dijit.Tree     
    dijit.byId("myTree")._itemNodesMap = {};
    dijit.byId("myTree").rootNode.state = "UNCHECKED";
    dijit.byId("myTree").model.root.children = null;

    // Destroy the widget
    dijit.byId("myTree").rootNode.destroyRecursive();

    // Recreate the model, (with the model again)
    dijit.byId("myTree").model.constructor(dijit.byId("myTree").model)

    // Rebuild the tree
    dijit.byId("myTree").postMixInProperties();
    dijit.byId("myTree")._load();

},

This will refresh your Tree.

这将刷新您的树。

回答by kcrossen

Here's a problem with Layke's solution (which otherwise does work) found by pre-production testing for a commercial website.

这是通过商业网站的预生产测试发现的 Layke 解决方案(否则会起作用)的问题。

Case 1:

情况1:

  • Create & populate a tree.
  • Click on a node to select.
  • Execute refreshTree as in Layke's solution.
  • Click on a node, get error "this.labelNode is undefined".
  • 创建并填充一棵树。
  • 单击要选择的节点。
  • 在 Layke 的解决方案中执行 refreshTree。
  • 单击一个节点,得到错误“this.labelNode 未定义”。

Now start again, case 2:

现在重新开始,情况2:

  • Create & populate a tree.
  • Click on a node to select.
  • Ctrl-click on the previously selected node.
  • Execute refreshTree as in Layke's solution.
  • Click on a node, no error.
  • 创建并填充一棵树。
  • 单击要选择的节点。
  • 按住 Ctrl 键单击先前选择的节点。
  • 在 Layke 的解决方案中执行 refreshTree。
  • 单击一个节点,没有错误。

The stored selection references to the first selection are being used to undo the selection attributes (background color, etc.) when the second selection is made. Unfortunately, the referred-to objects are now in the bit-bucket. The modified code appears to be production-ready, i.e. hasn't failed any pre-production tests.

存储的对第一个选择的选择引用用于在进行第二个选择时撤消选择属性(背景颜色等)。不幸的是,被引用的对象现在在位桶中。修改后的代码似乎可以用于生产,即没有通过任何预生产测试。

The solution is to put:

解决办法是把:

Tree.dndController.selectNone();

prior to first line of Layke's refreshTree solution above.

在上面 Layke 的 refreshTree 解决方案的第一行之前。

In response to meta suggestions, here it is:

为了回应元建议,这里是:

refreshTree : function() {
    // Destruct the references to any selected nodes so that 
    // the refreshed tree will not attempt to unselect destructed nodes
    // when a new selection is made.
    // These references are contained in Tree.selectedItem,
    // Tree.selectedItems, Tree.selectedNode, and Tree.selectedNodes.
    Tree.dndController.selectNone();

    Tree.model.store.clearOnClose = true;
    Tree.model.store.close();

    // Completely delete every node from the dijit.Tree     
    Tree._itemNodesMap = {};
    Tree.rootNode.state = "UNCHECKED";
    Tree.model.root.children = null;

    // Destroy the widget
    Tree.rootNode.destroyRecursive();

    // Recreate the model, (with the model again)
    Tree.model.constructor(dijit.byId("myTree").model)

    // Rebuild the tree
    Tree.postMixInProperties();
    Tree._load();

}

回答by Taneeda

Thanks for this function, works great in my tree.

感谢这个功能,在我的树上效果很好。

A notice to those who are new to dojo (like me)... After creation of the tree, it is needed to extend the tree with the refresh function:

给刚接触dojo的人(像我一样)的注意事项...创建树后,需要使用刷新功能扩展树:

dojo.extend(dijit.Tree, {
    refresh: function() {
        this.dndController.selectNone();
        //...
    }
});

Then you can call the function with:

然后您可以使用以下命令调用该函数:

dijit.byId('myTree').refresh();

回答by Tigertron

Updating your store will automatically update your tree!

更新您的商店将自动更新您的树!

  1. You need a FileWriteStore, which gives you the ability to modify your data.
  2. Use the store to fetch the items you want to update via query.
  3. Update each item returned.
  4. Then save the store and the tree will update.

    FileWriteStore.fetch({
        query: { color: "red" },
        onComplete: function(items){
            for (var i = 0; i < items.length; i++){
                FileWriteStore.setValue(items[i], "color", "green");
            }
            FileWriteStore.save();              
        }
    });
    
  1. 您需要一个 FileWriteStore,它使您能够修改数据。
  2. 使用商店通过查询获取您要更新的项目。
  3. 更新返回的每个项目。
  4. 然后保存商店,树将更新。

    FileWriteStore.fetch({
        query: { color: "red" },
        onComplete: function(items){
            for (var i = 0; i < items.length; i++){
                FileWriteStore.setValue(items[i], "color", "green");
            }
            FileWriteStore.save();              
        }
    });
    

回答by Markus Kühn

Layke's solution did not work for me. I am using dojo 1.9.1. My store is of type "ItemFileWriteStore" and the model of type "TreeStoreModel".

Layke 的解决方案对我不起作用。我正在使用道场 1.9.1。我的商店是“ItemFileWriteStore”类型和“TreeStoreModel”类型的模型。

myStore = new ItemFileWriteStore({
    url : "../jaxrs/group/tree"
});

itemModel = new TreeStoreModel({
    store : myStore,
    query : {
        id : "0"
    }
});
parser.parse();

This works for me:

这对我有用:

var tree = dijit.byId('myTree');
tree.dndController.selectNone(); 
tree._itemNodesMap = {};
tree.model.root = null;
tree.model.store.clearOnClose = true;
tree.model.store.urlPreventCache = true;
tree.model.store.revert(); 
tree.model.store.close();
tree.rootNode.state = "UNCHECKED";
if (tree.rootNode) {
    tree.rootNode.destroyRecursive();
}
tree.postMixInProperties();
tree._load();

回答by Alex Boisselle

While going through these answers I've built my own method to update specific nodes once at a time and NOT need the refresh.

在浏览这些答案时,我已经构建了自己的方法来一次更新特定节点并且不需要刷新。

_refreshNodeMapping: function (newNodeData) {

    if(!this._itemNodesMap[newNodeData.identity]) return;

    var nodeMapToRefresh = this._itemNodesMap[newNodeData.identity][0].item;
    var domNode = this._itemNodesMap[newNodeData.identity][0].domNode;

    //For every updated value, reset the old ones
    for(var val in newNodeData)
    {
        nodeMapToRefresh[val] = newNodeData[val];

        if(val == 'label')
        {
            domNode.innerHTML = newNodeData[val];
        }
    }  
}

回答by Andy

Not supported at present. See here.

目前不支持。见这里