Does TreeList support pagination

7 posts, 0 answers
  1. Vincent
    Vincent avatar
    1 posts
    Member since:
    Oct 2014

    Posted 11 Feb 2015 Link to this post

    There is an example named "Example - set dataSource as an existing kendo.data.TreeListDataSource instance" in the document at "http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist".

    I tried the example and got nothing. I then traced the code of the kendo.treelist.js file and found no pageable property in it.

    I'm wondering whether TreeList support pagination. Thanks.
  2. Alex Gyoshev
    Admin
    Alex Gyoshev avatar
    2500 posts

    Posted 11 Feb 2015 Link to this post

    Hello Vincent,

    No, the TreeList does not support paging by design. Implementing paging over a hierarchical collection is not optimal as an algorithm (because it involves getting the complete hierarchy from the database), nor is the end-result user-friendly (because navigation via paging does not make sense to users). If you need to show a large amount of data in the TreeList, use remote loading.

    Regards,
    Alex Gyoshev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  3. Kendo UI is VS 2017 Ready
  4. Morten
    Morten avatar
    6 posts
    Member since:
    Mar 2015

    Posted 29 Apr 2015 in reply to Alex Gyoshev Link to this post

    Hi, while I agree that paging on a single root hierarchy makes little sense.

    However if the hierarchy consists of multiple roots. Then paging by roots is just as user-friendly as any other grid with paging. Hierarchies with many children per node is a problem, but that's problem for another day :)

    Solving this problem using OData makes extracting data quite simple.

    Example getting roots with paging:

    GET ~/Products?$filter=ParentId eq null&$expand=Children&$top={pagesize}&$skip={skipnumber}&$count=true 
    Expansion depth can be controlled via $expand=Children($levels=#) if nessarcy

    The result would be:

    {
        "@odata.count": 33,
        "value": [
            {
                "Id": 1,
                "ParentId": null,
                ...,
                "Children": [
                    {
                        "Id": 2,
                        "ParentId": 1,
                        ...,
                    }
                ]
            },
            ...
        ]
    }

    And for filtering the query would look like:

    GET ~/Products?$filter={expr}&$expand=Parent&$top={pagesize}&$skip={skipnumber}&$count=true

    Where {expr} could be something like: contains(Name, 'some value')

    The result would be:

    {
        "@odata.count": 3,
        "value": [
            {
                "Id": 3,
                "ParentId": 1,
                ...,
                "Parent": {
                    "Id": 1,
                    "ParentId": null,
                    ...,
                }
            },
            ...
        ]
    }

    Note that the structure is flipped (Child -> Parent, duplicate Parent objects is also a problem). But that's workable. A javascript function could fix it.

  5. T. Tsonev
    Admin
    T. Tsonev avatar
    2770 posts

    Posted 02 May 2015 Link to this post

    Hi,

    Thank you for sharing this idea for paging in the TreeList.
    It demonstrates that this is possible to to with an OData back-end. It also shows that the process is somewhat involved.

    My main concern here is that we can't rely on OData for a specific feature. Customers will have to be able to implement it with their own services. This is where things start to get challenging.

    What we can do is to take a working implemetation of this and publish it as how-to guide. This will allow us to highlight any specific requirements and will make it clear that this is not an universal solution.

    Regards,
    T. Tsonev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  6. Morten
    Morten avatar
    6 posts
    Member since:
    Mar 2015

    Posted 15 May 2015 Link to this post

    Here's a working Angular example using OData.

    Paging, filtering and sorting works :-)

    View:

    <kendo-treelist k-options="treeListOptions"></kendo-treelist>
    <kendo-pager k-options="pagerOptions"></kendo-pager>

    Controller logic:

    // default filtering and sorting
    var defaultFilter = { field: "ParentId", operator: "eq", value: null };
    var defaultSort = { field: "Name", dir: "asc" };
     
    var myODataSource = new kendo.data.DataSource({
        type: "odata-v4",
        transport: {
            read: {
                url: "/odata/Products",
                data: {
                    "$expand": "Children($levels=max)"
                }
            }
        },
        pageSize: 15,
        serverPaging: true,
        serverSorting: true,
        serverFiltering: true,
        filter: defaultFilter,
        sort: defaultSort,
        schema: {
            parse: function(response) {
                if (myODataSource.transport.options.read.data.$expand == "Parent($levels=max)") {
                    // if "$expand=Parent($levels=max)" then the hierarchy will be reversed Children -> Parent
                    // thus we need to flatten Parents
                    var ary = _.flattenHierarchy(response.value, 'Parent');
                    // and remove duplicate parents coming from different tree branches
                    response.value = _.uniq(ary);
                } else {
                    // if "$expand=Children($levels=max)" then the hierarchy will be as expected Parent -> Children
                    // thus we need to flatten Children
                    response.value = _.flattenHierarchy(response.value, 'Children');
                }
     
                return response;
            }
        },
        change: function(e) {
            treeListDataSource.read();
        }
    });
     
    // filter hack!
    var originalFilterFn = kendo.data.TreeListDataSource.fn.filter;
    kendo.data.TreeListDataSource.fn.filter = function (e) {
        if (arguments.length > 0) {
            if (e === null) {
                // if e is null, then the filter is cleared. So we need to filter by roots to get the normal tree
                myODataSource.transport.options.read.data.$expand = "Children($levels=max)";
                myODataSource.filter(defaultFilter);
            } else {
                // else we're filtering and the result nodes need to include parents to maintain the tree hierarchy
                myODataSource.transport.options.read.data.$expand = "Parent($levels=max)";
                myODataSource.filter(e);
            }
        }
     
        return originalFilterFn.apply(this, arguments);
    };
     
    // sort hack!
    var originalSortFn = kendo.data.TreeListDataSource.fn.sort;
    kendo.data.TreeListDataSource.fn.sort = function (e) {
        if (arguments.length > 0) {
            myODataSource.sort(e);
        }
     
        return originalSortFn.apply(this, arguments);
    };
     
    var treeListDataSource = new kendo.data.TreeListDataSource({
        transport: {
            read: function (options) {
                var data = myODataSource.data().toJSON();
                options.success(data);
            }
        },
        sort: defaultSort,
        schema: {
            model: {
                id: "Id",
                fields: {
                    parentId: { field: "ParentId", type: "number", nullable: true },
                    Id: { field: "Id", type: "number" }
                },
                expanded: true
            }
        }
    });
     
    $scope.treeListOptions = {
        autoBind: false,
        dataSource: treeListDataSource,
        filterable: true, //{ mode: "row"}, not supported (yet) by treelist
        sortable: true,
        resizable: true,
        reorderable: true,
        columns: [
            { field: "Name" },
            { field: "Description" }
        ]
    };
     
    $scope.pagerOptions = {
        autoBind: false,
        dataSource: myODataSource,
        info: true,
        pageSizes: [2, 3, 4, 5, 6],
        refresh: true,
    };
     
    myODataSource.read();

    Underscore function

    _.mixin({
        flattenHierarchy: function self(objAry, childPropertyName) {
            // default values
            childPropertyName = typeof childPropertyName !== 'undefined' ? childPropertyName : 'children';
     
            var result = [];
            _.each(objAry, function(obj) {
                // the object it self without children
                var strippedObj = _.omit(obj, childPropertyName);
                result.push(strippedObj);
     
                if (obj.hasOwnProperty(childPropertyName) && obj[childPropertyName] !== null) {
                    // child object(s)
                    var children = obj[childPropertyName];
                    if (!_.isArray(children))
                        children = [children];
                     
                    result.pushArray(self(children, childPropertyName));
                }
            });
     
            return result;
        }
    });

    Enjoy!

  7. T. Tsonev
    Admin
    T. Tsonev avatar
    2770 posts

    Posted 19 May 2015 Link to this post

    Hello Morten,

    Thanks for sharing this solution.

    Regards,
    T. Tsonev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  8. Nayana
    Nayana avatar
    3 posts
    Member since:
    Sep 2015

    Posted 06 Jan in reply to T. Tsonev Link to this post

    Hello,

    Is there a way we can sort the column on all pages? I have implemented treeList as mentioned above. I need to sort on column for all pages? How can this be done?

     

    Thanks in advance.

Back to Top
Kendo UI is VS 2017 Ready