通过asp:hiddenfield通过回发在jstree中保留json数据

时间:2010-09-02 18:44:58

标签: asp.net jquery json jstree

我已经花了好几个小时,我还没有取得很大进展,所以我希望其中一位出色的SO大家可以帮助我。这是问题......

我正在通过jQuery的jQuery插件实现一个树。我正在从我们的webapp以编程方式将数据填充到树中,通过json转储到asp:HiddenField中,基本上就像这样:

JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(Items);

json = json.ToLower();
data.Value = json;    

然后,树从隐藏字段中拉出json以构建自身。这完全正常,直到我尝试保留选择/打开节点的数据。为了简化我的问题,我将一些json数据硬编码到树中,并尝试使用cookie插件来保存树状态数据。这无论出于何种原因都不起作用。我已经看到其他问题,人们需要按特定顺序加载插件等,这并没有解决我的问题。我尝试使用html_data进行相同的设置,它完美无缺。通过这种工作持久性,我将cookie插件转换为将数据保存在不同的asp:hiddenfield中(我们的应用程序中不能使用cookie作为此类事物。)

本质上cookie操作是相同的,它只是将节点数组保存为隐藏字段的值。这适用于html_data,仍然没有json,我还没有能够把手指放在它失败的地方。

这是jQuery.cookie.js的替代品:

jQuery.persist = function(name, value) {
    if (typeof value != 'undefined') { // name and value given, set persist
        if (value === null) {
            value = '';
        }
        jQuery('#' + name).attr('value', value);
    } else { // only name given, get value
        var persistValue = null;
        persistValue = jQuery('#' + name).attr('value');
        return persistValue;
    }
};

除了一些变量名称更改外,jstree.cookie.js代码完全相同。 这是我的树:

$(function() {
                $("#demo1").jstree({
                    "json_data": {
                        "data" : [
                        {
                            "data" : "A node",
                            "children" : [ "Child 1", "Child 2" ]
                        },
                        {
                            "attr": { "id": "li.node.id" },
                            "data" : {
                                "title": "li.node.id",
                                "attr": { "href": "#" }
                            },
                            "children": ["Child 1", "Child 2"]
                        }
                    ]
                    },
                    "persistence": {
                        "save_opened": "<%= open.ClientID %>",
                        "save_selected": "<%= select.ClientID %>",
                        "auto_save": true
                    },
                   "plugins": ["themes", "ui", "persistence", "json_data"]
                });
            });

数据 - 被正确存储在隐藏字段中,问题发生在回发上,它不会重新打开节点。任何帮助将不胜感激。

在仔细研究了这个之后,我只想解释一下,在我看来,问题是在尝试执行持久性操作时,尚未从JSON_data构建树。有没有办法推迟这些操作,直到树完全加载?

2 个答案:

答案 0 :(得分:2)

如果有人仍在尝试在jsTree 3.0+版本上执行相同类型的操作,则可以更轻松地完成相同类型的功能,而无需编辑任何jsTree的核心JavaScript,也无需依赖在&#34;州&#34;插件(版本1.0 - &#34;持久性&#34;):

var jsTreeControl = $("#jsTreeControl");
//Can be a "asp:HiddenField"
var stateJSONControl = $("#stateJSONControl");
var url = "exampleURL";

jsTreeControl.jstree({
    'core': {
        "data": function (node, cb) {
            var thisVar = this;

            //On the initial load, if the "state" already exists in the hidden value 
            //then simply use that rather than make a AJAX call
            if (stateJSONControl.val() !== "" && node.id === "#") {
                cb.call(thisVar, { d: JSON.parse(stateJSONControl.val()) });
            }
            else {
                $.ajax({
                    type: "POST",
                    url: url,
                    async: true,
                    success: function (json) {
                        cb.call(thisVar, json);
                    },
                    contentType: "application/json; charset=utf-8",
                    dataType: "json"
                }).responseText;
            }
        }
    }
});

//If the user changes the jsTree, save the full JSON of the jsTree into the hidden value, 
//this will then be restored on postback by the "data" function in the jsTree decleration
jsTreeControl.on("changed.jstree", function (e, data) {
    if (typeof (data.node) != 'undefined') {
        stateJSONControl.val(JSON.stringify(jsTreeControl.jstree(true).get_json()));
    }
});

此代码将创建一个jsTree并保存它&#34; state&#34;进入隐藏值,然后在重新创建jsTree时回发,它将使用其旧的&#34;状态&#34;从&#34; HiddenField&#34;恢复而不是进行新的AJAX调用并丢失用户所做的扩展/选择。

答案 1 :(得分:1)

使用JSON数据正常工作。我不得不在jstree里面编辑“重新打开”和“重新选择”功能。

以下是需要它的任何人的新功能重新打开功能。

reopen: function(is_callback) {
                var _this = this,
                    done = true,
                    current = [],
                    remaining = [];
                if (!is_callback) { this.data.core.reopen = false; this.data.core.refreshing = true; }
                if (this.data.core.to_open.length) {
                    $.each(this.data.core.to_open, function(i, val) {
                        val = val.replace(/^#/, "")
                        if (val == "#") { return true; }
                        if ($(("li[id=" + val + "]")).length && $(("li[id=" + val + "]")).is(".jstree-closed")) { current.push($(("li[id=" + val + "]"))); }
                        else { remaining.push(val); }
                    });
                    if (current.length) {
                        this.data.core.to_open = remaining;
                        $.each(current, function(i, val) {
                            _this.open_node(val, function() { _this.reopen(true); }, true);
                        });
                        done = false;
                    }
                }
                if (done) {
                    // TODO: find a more elegant approach to syncronizing returning requests
                    if (this.data.core.reopen) { clearTimeout(this.data.core.reopen); }
                    this.data.core.reopen = setTimeout(function() { _this.__callback({}, _this); }, 50);
                    this.data.core.refreshing = false;
                }
            },

问题是它试图通过自定义属性找到

  • 元素。它只是将这些字符串推入数组,以便在期望节点对象时进行搜索。使用此行

    if ($(("li[id=" + val + "]")).length && $(("li[id=" + val + "]")).is(".jstree-closed")) { current.push($(("li[id=" + val + "]"))); }
    

    而不是

    if ($(val).length && $(val).is(".jstree-closed")) { current.push(val); }
    

    就这么做了。使用类似的过程,我也能够以这种方式保留选定的节点。

    希望这对某人有所帮助。