Сохранение данных json в jstree посредством обратной передачи через asp: hiddenfield - PullRequest
1 голос
/ 02 сентября 2010

Я пролил это на несколько часов, и мне еще многое предстоит сделать, поэтому я надеялся, что один из замечательных обитателей СО сможет мне помочь. Вот в чем проблема ...

Я реализую дерево через плагин jstree для jQuery. Я извлекаю данные, которыми я заполняю дерево программно из нашего веб-приложения через 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: hidden (мы не можем использовать куки для такого типа вещей в нашем приложении.)

по сути, операции с 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 ]

2 голосов
/ 26 февраля 2016

Если кто-то все еще пытается выполнить операцию такого же типа на jsTree версии 3.0+, существует более простой способ реализовать функциональность того же типа, без редактирования какого-либо основного JavaScript-кода jsTree и без использования состояния «состояние». Плагин (Версия 1.0 - «Постоянство»):

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 и сохранит его «состояние» в скрытом значении, затем при обратной передаче, когда jsTree будет воссоздан, он будет использовать свое старое «состояние», восстановленное из «HiddenField», вместо того, чтобы делать новый вызов AJAX. и потерять расширения / выборы, сделанные пользователем.

1 голос
/ 03 сентября 2010

Правильно работает с данными 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); }

было все, что нужно. Используя аналогичный процесс, я смог сохранить выбранные узлы таким же образом.

Надеюсь, это кому-нибудь поможет.

...