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

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

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

Может кто-то указать на примеры кода? Как много из вышеперечисленного поддерживается из коробки "Kendo"?

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

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>

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

<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

КАК НАЧАТЬ НАЧИНАЕТСЯ;

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

КОНЕЦ

Другие вопросы по тегам