【问题标题】:Recursively expanding tree nodes in ExtJSExtJS中递归扩展树节点
【发布时间】:2014-07-12 15:29:42
【问题描述】:

我正在寻找一种递归扩展树节点的方法。树还没有装满。我们一次只加载一个深度级别。因此,例如,如果我的路径有 3 个深度级别(/nodeId1/nodeId14/nodeId142)我想加载第一个节点,然后通过我的路径中的第二个 ID 获取 2 级节点(在本例中为 nodeId14)展开它,然后得到第三个等。

然而,当一个节点被扩展时,代理会调用 AJAX 来获取节点子节点的数据,并且由于该调用是异步的,因此程序本身会在请求完成之前尝试继续扩展下一级节点是时候完成给我一个“节点未定义错误”了,因为级别 2 尚未加载。

我一直在寻找如何解决这个问题的 1 天,但没有任何帮助。我发现一个博客解决了同样的问题,但这篇文章是 2009 年的,他使用的一些东西已被弃用。

http://hamisageek.blogspot.gr/2009/04/extjs-tip-recusively-opening-nodes-in.html

一些帮助的代码:

Ext.define('treeStore', 
{
    extend : 'Ext.data.TreeStore',
    alias: 'widget.treeStore',
    autoLoad : false,
    model : 'treeModel',
    root :  {
        id: 0,
        name : 'Root', 
        expanded : true,
        loaded: true
    },
    proxy :  {
        type : 'ajax', 
        url : 'MyServlet', 
        reader :  {
            type : 'json', 
            root : 'children'
        }
    },
    folderSort: true
});

Ext.define('Ext.tree.Panel',{
.
.
.
//Stuff about the tree panel etc.
dockedItems: {
        xtype: 'textfield',
        name: 'Search',
        allowBlank: true,
        enableKeys: true,
        listeners: { 
            specialkey: function (txtField, e) { 
                if (e.getKey() == e.ENTER){
                    var searchValue = txtField.getValue();
                    Ext.Ajax.request({
                        url: 'MyServlet',
                        params: {
                            caseType: 'search',
                            value: searchValue
                        },
                        success: function(response) { //ATTENTION: When calling the .expand() the AJAX hasn't finished and cannot find the node.
                            response = Ext.decode(response.responseText);
                            var panel = txtField.up();
                            response.IDs.forEach(function(entry){
                                panel.getStore().getNodeById(entry.folderId).expand(); <-problem here
                            });
                        }
                    });
                }
            }
        }
    }

我尝试向 expand() 回调添加函数,我尝试过延迟任务,我尝试过 setTimer 等,但没有任何效果。我真的没有选择,这似乎是一件很简单的事情,但它让我发疯。

【问题讨论】:

    标签: recursion extjs tree panel


    【解决方案1】:

    如果您有要扩展的节点的路径,例如从先前调用 getPath 中保存的路径

    var path = node.getPath();
    

    那么任务就很简单了:

    tree.expandPath(path);
    

    您可以在http://docs.sencha.com/extjs/4.2.2/extjs-build/examples/build/KitchenSink/ext-theme-neptune/#tree-reorder 上通过输入控制台来测试这种方法:

    Ext.ComponentQuery.query('treepanel[title=Files]')[0].expandPath('/Ext JS/app/domain', 'text');
    

    如果你没有路径但你决定在父级展开(加载)后扩展哪个子级,则任务会更加繁琐。在这种情况下,您可能会使用 callback 函数进行扩展,并在回调中继续扩展子项。

    详情请见node.expand

    【讨论】:

      【解决方案2】:

      这是一个带有大量评论的更新解决方案,以帮助人们了解正在发生的事情:

      TreePanel: {
          a: {},
          bunch: {},
          of: {},
          stuff: {},
      
          dockedItems: {
              xtype: 'textfield',
              name: 'Search Field',
              allowBlank: true,
              enableKeys: true,
              listeners: {
                  specialkey: function (textfield, keypressEvent) {
                      if (keypressEvent.getKey() == keypressEvent.ENTER) {
                          treePanelReference.searchFunction(textfield.getValue());
                      }
                  }
              }
          },
      
          searchFunction: function (searchKey) {
              var treepanel = this; //Keeping a reference on the treepanel to have access to its functions inside the `success` callback.
              Ext.Ajax.request({
                  url: '/api/folders/search',
                  params: {
                      value: searchKey
                  },
                  success: function(response) {
                      response = Ext.decode(response.responseText);
                      treepanel.expandFn(-1, response);
                  };
              });
          },
      
          expandFn: function(index, response) { //Recursive function.
              var folders = response.folders;//This array contains all the folders of the path ordered from the root folder to the one we are searching for.
              var node = this.getStore().getNodeById(folders[folders.length-1].folderId);//Attempt to fetch the selected folder (it is the last folder in the array) if it has been loaded.
              if (!node) {//If it can't find the node it means it hasn't been loaded, we have to load each folder on the path one by one until we find the one we are looking for.
                  var i = index + 1;
                  var nextNode = this.getStore().getNodeById(folders[i].folderId);
                  if (!nextNode.isExpanded() && !nextNode.isLoaded()) { //If we arrive at a folder that isn't loaded we have to load it.
                      //Because loading takes time, all actions that are to take place after the load are put in this callback function
                      //that will be called after the folder has been loaded and expanded.
                      //We use Ext.pass to have easier control over the scope and arguments.
                      //We also add {single: true} so that the function isn't called again if we manually reload the node at some point.
                      nextNode.on("expand", Ext.pass(this.expandFn, [this, i, response]), this, {single:true});
                      nextNode.expand();
                  }
                  else if (!nextNode.isExpanded() && nextNode.isLoaded()) {//If the folder has been loaded but not expanded we simply expand it.
                      nextNode.expand();
                      this.expandFn(this, i, response);
                  }
                  else {
                      //Every call to expandFn is made in order to load the next folder on the path,
                      //recursively until we end up loading its immediate parent node at which point
                      //we exit the recursion.
                      this.expandFn(this, i, response);
                  }
              }
              else {
                  //We arrive here if in the previous recursion step we ended up loading the searched folder's immediate parent
                  //and the call to `getNodeById` returns the folder we're looking for.
                  //Here we expand the whole path (it might not be expanded fully) up to the folder we are searching for and we also select and focus it.
                  this.expandPath(node.getPath(), {select: true});
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-04
        • 1970-01-01
        • 2017-09-26
        • 2014-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多