首页 文章

在ExtJS中递归扩展树节点

提问于
浏览
3

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

但是,当一个节点被扩展时,代理会有一个AJAX调用来获取节点子节点的数据,并且由于这个调用是异步的,所以在请求有时间完成之前,程序本身会尝试继续扩展下一级节点 . 给我一个'节点未定义错误',因为级别2还没有加载 .

我一直在寻找如何解决这个问题的一天,但没有任何帮助 . 我发现一个博客解决了同样的问题,但帖子是从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()回调添加函数,我尝试过delayedtask,我尝试过setTimer等,但没有任何作用 . 我真的没有选择,这似乎是一件很简单的事情,但它让我疯狂 .

2 回答

  • 1

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

    var path = node.getPath();
    

    然后任务是微不足道的:

    tree.expandPath(path);
    

    您可以通过键入console在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

  • 4

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

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

相关问题