Ленивая загрузка в дереве Kendo UI с кэшированием

Я использую Kendo UI TreeView для загрузки иерархических данных на моей веб-странице. По умолчанию я загружаю данные до 3-х уровней (т.е. Root -> Root directs -> Root directs' directs). Мне нужен способ лениво загружать оставшиеся узлы по мере того, как пользователь расширяется дальше по дереву. Кроме того, уже извлеченные данные должны кэшироваться локально, чтобы избежать ненужных вызовов для уже развернутых узлов. Я новичок в Kendo UI, и у меня нет времени на изучение документации. json выглядит так

   {
      Id: '1',
      ParentId: '-1',
      Payload: {... }
      Children: [
          Id: '2',
          ParentId: '1',
          PayLoad: {...},
          Children: [{...}]
          ]
            ....
    }

Может ли кто-нибудь указать образцы кода? Сколько из вышеперечисленного поддерживается кендо «из коробки»?

Заранее спасибо.


person prthrokz    schedule 09.12.2013    source источник


Ответы (2)


Эта функциональность не поддерживается стандартной конфигурацией, но ее можно реализовать с помощью пользовательского транспорта. Вот как создать гибридные источники данных, которые работают с массивом localData, если элементы доступны, и в противном случае выполняют запросы к серверу.

var localData = [
  { id: 1, text: "Node 1", hasChildren: true, items: [
    { id: 101, text: "Node 1.1", hasChildren: true, items: [
      { id: 10101, text: "Node 1.1.1" }
    ] }
  ] }, 
  { id: 2, hasChildren: true, text: "Node 2" },
  { id: 3, hasChildren: true, text: "Node 3" }
];

function get(data, id) {
  if (!id) {
    return data;
  } else {
    for (var i = 0; i < data.length; i++) {
      if (data[i].id == id) {
        return data[i].items;
      } else if (data[i].items) {
        var result = get(data[i].items, id);
        if (result) return result;
      }
    }
  }
}

var homogeneous = new kendo.data.HierarchicalDataSource({
  transport: {
    read: function (options) {
      var id = options.data.id;
      var data = get(localData, id);
      if (data) {
        options.success(data);
      } else {
        // mock call to server with static data
        // you can use $.ajax() and call options.success(data) on success
        setTimeout(function() {
          options.success([
            { id: id + 1, text: "Remote node 1", hasChildren: false },
            { id: id + 2, text: "Remote node 2", hasChildren: true }
          ]);
        }, 1000);
      }
    }
  },
  schema: {
    model: {
      id: "id"
    }
  }
});

$("#tree").kendoTreeView({
  dataSource: homogeneous
});
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.default.min.css" rel="stylesheet" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.1.319/js/kendo.web.min.js"></script>
<div id="tree"></div>

person Alex Gyoshev    schedule 13.12.2013
comment
Не могли бы вы опубликовать свое решение? Я работаю с этим предложением jsBin в течение нескольких дней и до сих пор не могу заставить работать второй уровень. Пожалуйста. - person Amanda; 14.03.2014

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

<div id="treeview"> </div>

<script>
    var serviceRoot = "http://<local name>:58754/api/";

    var localData;

    $(document).ready(function () {        

        var homogeneous = new kendo.data.HierarchicalDataSource({
            transport: {
                read: function (options) {
                    if (typeof options.data.ID != 'undefined') {
                        var id = options.data.ID;
                        var data = getNextLevel(localData, id);
                        if (data) {
                            options.success(data);
                        } else {
                            var currentnode = get(localData, id);
                            if (currentnode.Level == 1) {
                                $.ajax({
                                    url: serviceRoot + "tree",
                                    data: 'ID=' + currentnode.ID + '&Level=' + currentnode.Level,
                                    type: "Get",
                                    success: function (result) {
                                        setTimeout(function () {
                                            var res = result;
                                            addToLocalData(localData, res, currentnode.ID);
                                            options.success(res);
                                        }, 1000);

                                    },
                                    error: function (result) {
                                        options.error(result);
                                    }
                                });
                            } else {
                                if (currentnode.Level == 2) {
                                    $.ajax({
                                        url: serviceRoot + "tree",
                                        data: 'ID=' + currentnode.ID + '&Level=' + currentnode.Level,
                                        type: "Get",
                                        success: function (result) {
                                            setTimeout(function () {
                                                var res = result;
                                                addToLocalData(localData, res, currentnode.ID);
                                                options.success(res);
                                            }, 1000);                                            
                                        },
                                        error: function (result) {
                                            options.error(result);
                                        }
                                    });
                                }
                            }
                        }
                    }
                    else {
                        $.ajax({
                            url: serviceRoot + "tree",
                            data: 'ID='+ null +'&Level='+ null,
                            type: "Get",
                            success: function (result) {
                                setTimeout(function () {
                                    options.success(result);
                                }, 1000);
                                localData = result;
                            },
                            error: function (result) {
                                options.error(result);
                            }
                        });
                    }
                }
            },
            schema: {
                model: {
                    id: "ID",
                    hasChildren: "HasChildren"
                }
            }
        });
        $("#treeview").kendoTreeView({
            dataSource: homogeneous,
            dataTextField: "Name"
        });
    });    

    //Checks if nodes are already in the tree and returns it if it does
    function getNextLevel(data, id) {
        if (!id) {
            return data;
        } else {
            for (var i = 0; i < data.length; i++) {
                if (data[i].ID == id) {
                    return data[i].Items;
                } else if (data[i].Items) {
                    for (var j = 0; j < data[i].Items.length; j++) {
                        if (data[i].Items[j].ID == id) {
                            return data[i].Items[j].Items;
                        }
                    }
                }
            }
        }
    }

    //Get Tree object for a given ID
    function get(data, id) {
        if (id) {
            for (var i = 0; i < data.length; i++) {
                if (data[i].ID == id) {
                    return data[i];
                }
                else if (data[i].Items) {
                    for (var j = 0; j < data[i].Items.length; j++) {
                        if (data[i].Items[j].ID == id) {
                            return data[i].Items[j];
                        }
                    }
                }
            }
        }
        return null;
    }

    //Add newly read nodes to cached tree
    function addToLocalData(localdata, data, id) {
        if (!id) {
            return localdata;
        } else {
            for (var i = 0; i < localdata.length; i++) {
                if (localdata[i].ID == id) {
                    localdata[i].Items = data;
                    return;
                } else {
                    if (localdata[i].Items) {
                        for (var j = 0; j < localdata[i].Items.length; j++) {
                            if (localdata[i].Items[j].ID == id) {
                                localdata[i].Items[j].Items = data;
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

</script>

Я использую хранимую процедуру для чтения значений из 3 таблиц в объект Tree. Вот код объекта Tree:

public class Tree
{
    public Guid ID { get; set; }
    public string Name { get; set; }
    public bool HasChildren { get; set; }
    public int Level { get; set; }
    public IEnumerable<Tree> Items { get; set; }
}

И моя хранимая процедура:

ALTER PROCEDURE [dbo].[GetTreeItems] 
@ID uniqueidentifier, @CurrentLevel int

КАК НАЧАТЬ УСТАНОВИТЬ NOCOUNT ON;

if @CurrentLevel is null
    select IDStation as ID, StationName as Name, null as IDParent, 1 as [Level] ,
    case when (select COUNT(*) from Unit where Unit.IDStation = Station.IDStation) > 0 then 1 else 0 end as HasChildren
    from Station
    order by [Level], Name
--union

else if @CurrentLevel = 1
    select IDUnit as ID, UnitName as Name, Station.IDStation as IDParent, 2 as [Level], 
    case when (select COUNT(*) from Component where Component.IDUnit = Unit.IDUnit) > 0 then 1 else 0 end as HasChildren
    from Unit inner join Station on Station.IDStation = Unit.IDStation
    where Station.IDStation = @ID
    order by [Level], Name
--union 

if @CurrentLevel = 2
    select IDComponent as ID, ComponentName as Name, Unit.IDUnit as IDParent, 
    3 as [Level], 0 as HasChildren
    from Component inner join Unit on unit.IDUnit = Component.IDUnit
    where Unit.IDUnit = @ID
    order by [Level], Name

КОНЕЦ

person Amanda    schedule 16.03.2014