【问题标题】:How do I auto expand/auto select added node when adding nodes to ExtJS 4.2 treepanel?向 ExtJS 4.2 树形面板添加节点时,如何自动展开/自动选择添加的节点?
【发布时间】:2014-02-01 06:40:57
【问题描述】:

提供的示例代码用于 ExtJS 4.2 树形面板。如果单击按钮,则对 PHP 的 Ajax 调用会向树中添加一个节点。

树开始时所有文件夹都关闭。

我想知道如何自动选择添加的节点,并在必要时自动扩展其父节点以显示选定的新添加节点。当前添加节点并刷新数据会导致树返回其初始状态,即所有文件夹都已关闭。

如果用户在添加节点之前恰好展开了一些节点,我想记住树的状态,并自动选择新选择的节点,必要时展开父节点。

我尝试了这个插件,但它不起作用: https://github.com/AlexTiTanium/ExtJsStatefulTree

对不起,最后的多个数据文件。我不知道如何在 PHP 中更新 JSON。

function setData(data, scope) {
    Ext.Ajax.request({
        url: 'data.php',
        method: 'POST',
        params: {
            data: data
        },
        success: function() {
            scope.store.getData(onGetData, scope);
        },
        failure: function() {
            alert('failure');
        },
    }, scope);
}       
function onGetData(store, scope, records, success) {
    //alert('here');
};
Ext.onReady(function() {
    Ext.create('Ext.tree.Panel', {
        title: 'Tree Refresh Example',
        itemId: 'treeComp',
        width: 300,
        height: 350,
        store: new SampleTreeData(),        
        rootVisible: false,
        listeners: {
            afterRender: function() {
                this.store.getData(onGetData, this);
            }
        },
        tbar: ['->', { 
            xtype: 'button', 
            text: 'Add Banana',
            value: "Banana",
            margin: '0 30 0 0',
            listeners: {
                click: function(comp) {
                    setData(comp.value, this.up('treepanel'));
                }
            }
        }, { 
            xtype: 'button', 
            text: 'Add Cabbage',
            value: "Cabbage",
            margin: '0 30 0 0',
            listeners: {
                click: function(comp) {
                    setData(comp.value, this.up('treepanel'));
                }
            }
        }, { 
            xtype: 'button', 
            text: 'Add Yogurt',
            value: "Yogurt",
            listeners: {
                click: function(comp) {
                    setData(comp.value, this.up('treepanel'));
                }
            }
        }, '->'],
        renderTo: 'content'
    });        
});

Ext.define('SampleTreeData', {
    extend: 'Ext.data.TreeStore',
    autoLoad: false,
    autoSync: false,
    proxy: {
        type: 'ajax',
        url : '',
        reader: {
            type: 'json',
            root: ''
        }
    },
    root: {
        expanded: true
    },  
    getData: function(callBack, scope) {
        var store = this;
        store.proxy.url = 'data.php';
        store.load({
            scope : scope,
            callback : function(records, operation, success) {
                if (Ext.isFunction(callBack)) {
                    callBack(store, scope, records, success);
                }
            }
        });
    }
});

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <link rel="stylesheet" type="text/css" href="../../../../ext-4.2.2.1144/resources/css/ext-all.css" />
    <script type="text/javascript" src="../../../../ext-4.2.2.1144/ext-all-debug.js"></script>
    <script type="text/javascript" src="refresh1.js"></script>
    <script type="text/javascript" src="SampleTreeData.js"></script>
</head>
<body style="width: 100%; height: 100%; margin: 0px; padding: 0px; background-color: #89E5BD;">
    <div id="content" style="margin: auto; width: 500px; height: 500px;"/>
</body>

<?php
$logref = fopen('data.log', 'w');
fwrite($logref, "Entered script.\n");

if(isset($_POST['data'])){
    fwrite($logref, $_POST['data'] . "\n");
    if($_POST['data'] == 'Banana') {
        $newdata = file_get_contents("banana.json");
    } else if($_POST['data'] == 'Cabbage') {
        $newdata = file_get_contents("cabbage.json");
    } else if($_POST['data'] == 'Yogurt') {
        $newdata = file_get_contents("yogurt.json");
    }
    file_put_contents("data.json", $newdata);
    echo 'success';
}else {
    fwrite($logref, "getData\n");
    $data = file_get_contents("data.json");
    echo $data;
}
fclose($logref);
?>

---------------- initial tree data --------------
[{ 
        text: "Tree Root", 
        expanded: true, 
        children: [ 
            { 
                text: "Fruits", 
                children: [ 
                    { leaf:true, text: "apple" }, 
                    { leaf:true, text: "orange" } 
                ] 
            }, 
            { 
                text: "Vegetables", 
                children: [ 
                    { leaf:true, text: "carrot" }, 
                    { leaf:true, text: "beet" }
                ] 
            }, 
            { 
                text: "Dairy", 
                children: [ 
                    { leaf:true, text: "milk" }, 
                    { leaf:true, text: "cheese" } 
                ] 
            } 
        ] 
    }]

----------- data if Banana is clicked -----------
[{ 
        text: "Tree Root", 
        expanded: true, 
        children: [ 
            { 
                text: "Fruits", 
                children: [ 
                    { leaf:true, text: "apple" }, 
                    { leaf:true, text: "orange" }, 
                    { leaf:true, text: "banana" } 
                ] 
            }, 
            { 
                text: "Vegetables", 
                children: [ 
                    { leaf:true, text: "carrot" }, 
                    { leaf:true, text: "beet" } 
                ] 
            }, 
            { 
                text: "Dairy", 
                children: [ 
                    { leaf:true, text: "milk" }, 
                    { leaf:true, text: "cheese" } 
                ] 
            } 
        ] 
    }]

----------- data if cabbage is clicked --------
[{ 
        text: "Tree Root", 
        expanded: true, 
        children: [ 
            { 
                text: "Fruits", 
                children: [ 
                    { leaf:true, text: "apple" }, 
                    { leaf:true, text: "orange" } 
                ] 
            }, 
            { 
                text: "Vegetables", 
                children: [ 
                    { leaf:true, text: "carrot" }, 
                    { leaf:true, text: "beet" }, 
                    { leaf:true, text: "cabbage" }
                ] 
            }, 
            { 
                text: "Dairy", 
                children: [ 
                    { leaf:true, text: "milk" }, 
                    { leaf:true, text: "cheese" } 
                ] 
            } 
        ] 
    }]

----------- data if yogurt is clicked -------
[{ 
        text: "Tree Root", 
        expanded: true, 
        children: [ 
            { 
                text: "Fruits", 
                children: [ 
                    { leaf:true, text: "apple" }, 
                    { leaf:true, text: "orange" } 
                ] 
            }, 
            { 
                text: "Vegetables", 
                children: [ 
                    { leaf:true, text: "carrot" }, 
                    { leaf:true, text: "beet" } 
                ] 
            }, 
            { 
                text: "Dairy", 
                children: [ 
                    { leaf:true, text: "milk" }, 
                    { leaf:true, text: "cheese" }, 
                    { leaf:true, text: "yogurt" }
                ] 
            } 
        ] 
    }]

【问题讨论】:

    标签: extjs tree state extjs4.2


    【解决方案1】:

    是否需要重新加载树?您是否在每个 ajax 上保存服务器端的数据?根据答案,我会以不同的方式处理这个问题。

    1. 您不需要重新加载。数据属于当前用户,但您必须存储其状态。
      a) 根本不重新加载。让 ExtJs 将节点添加到树中,您可以保持它的展开。让您的 ajax 调用更新服务器端数据,但不要重新加载树。缺点:如果你有一个错误,服务器端和客户端不能保证是相同的。
      b) 让 ExtJs 将节点添加到树中,您可以将其保持展开。运行时不保存到服务器,编辑完成后保存新结构。

    2. 您需要重新加载,因为在用户编辑时,服务器上的树可能会发生变化(例如独立用户之间的并发更新)。
      a) 我认为在这种情况下,您可以通过将 expanded: true 添加到节点来将树状态发送到服务器并从那里取回。

    例如当点击香蕉时让服务器返回:

    [{ 
        text: "Tree Root", 
        expanded: true, 
        children: [ 
            { 
                text: "Fruits", 
                children: [ 
                    { leaf:true, text: "apple" }, 
                    { leaf:true, text: "orange" }, 
                    { leaf:true, text: "banana", expanded: true } 
                ],
                expanded: true
            }, 
            { 
                text: "Vegetables", 
                children: [ 
                    { leaf:true, text: "carrot" }, 
                    { leaf:true, text: "beet" } 
                ] 
            }, 
            { 
                text: "Dairy", 
                children: [ 
                    { leaf:true, text: "milk" }, 
                    { leaf:true, text: "cheese" } 
                ] 
            } 
        ] 
    }]
    
    1. b) 您可以从服务器重新加载树,但您可以在本地保存它的状态。您可以使用 beforeload 事件将状态存储在对象中,然后使用 load 事件来扩展节点(也许其他事件更适合)。

    【讨论】:

    • 我将处理方案 2,因为可能有多个用户将对象添加到树中。我现在不期望其他用户添加的对象实时更新树,除非我添加一个节点并重新加载树,所以我得到其他人在此期间创建的任何新对象。有没有办法防止树在重新加载时进行硬刷新,这意味着不要折叠所有内容而只是用新节点更新现有树?即使这涉及覆盖树形面板类,如果您认为可行,我也愿意尝试一下。
    • 我认为扩展:true 应该足够了,不是吗?
    • 问题是,在我的情况下,当我添加一个节点时,我不会将树数据发送到服务器。我正在发布数据以创建一个对象。于是我再次查询得到树的数据,但是因为我没有保存树的数据,所以没办法保存哪些节点应该展开为真。但我想知道是否有一种方法可以将某些内容保存到本地存储中,即保存树节点的展开状态,然后在重新加载后沿着树向下走。当然,这仍然会导致最初关闭所有树节点,然后根据需要重新打开。试图避免这种情况。
    • @Greg 我完成了我的回答。我不会使用本地存储,而只是在一个变量中。当您使用最合适的事件时,节点不应显示全部折叠。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多