This is a migrated thread and some comments may be shown as answers.

Changing grid template with virtual scroll enabled

7 Answers 355 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Joel
Top achievements
Rank 1
Joel asked on 29 Dec 2011, 05:01 AM
On change template in code, the repainting of the grid doesn't seem to expand and produce scrollbars to match the new height of the update grid display.

Here's an example. To reproduce the issue, click on the 'Change Template' button:
http://jsfiddle.net/65kWY/20/

PS. Setting scrollable to true (non-virtual) works just fine.

7 Answers, 1 is accepted

Sort by
0
Joel
Top achievements
Rank 1
answered on 31 Dec 2011, 03:56 AM
Is there a way to get access to the VirtualScrollable object of the grid, once it's set up? I think calling the refresh method on that object would help me fix this issue.
0
Dustin
Top achievements
Rank 2
answered on 25 Jun 2013, 06:00 PM
I realize this is an old thread, but I'm having a very similar issue with a hierarchy. With the virtual scroll, when rows are expanded, they push things down but the scroll bar doesn't update.
0
Vladimir Iliev
Telerik team
answered on 28 Jun 2013, 06:47 AM
Hi Dustin,

 
You should refresh the grid virtualScrollable object on each detail row collapse / expand: 

grid = $("#grid").data("kendoGrid")
 
//reset the cached rowHeight:
grid._rowHeight = undefined;
//refresh the virtualScrollable option
grid.virtualScrollable.refresh();
Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Dustin
Top achievements
Rank 2
answered on 28 Jun 2013, 12:44 PM
Okay, I added your code to the detailExpand and detailCollapse events, but it appears to be working backwards. When I expand the last row in the grid, the details expand under the end of the grid and the scrollbar doesn't move, when I collapse, the event fires off before the actual collapse, so the scroll bar gets bigger, but there is nothing to scroll down to now. Then when I expand again, the even fires before the actual details come out, so the scroll bar shrinks back down, is there an event that happens after expand and after collapse?

EDIT: Also, I just noticed on a grid with a lot of data, if I virtual scroll to the bottom, then click to expand the bottom row, it jumps my position up about 100 rows and when your scroll to a new "page" it closes all your expanded items.
<div id="grid"></div>
 
    <script type="text/javascript">
 
        function getHeight() {
            return $(window).height() - 100 - $('.CustomHeader').height();
        }
 
 
        function resizeVirtualScroll() {
 
            grid = $("#grid").data("kendoGrid");
 
            //reset the cached rowHeight:
            grid._rowHeight = undefined;
            //refresh the virtualScrollable option
            grid.virtualScrollable.refresh();
 
        }
 
 
        // setup grid
        $(document).ready(function() {
 
            $("#grid").kendoGrid({
                dataSource: aumData,
                navigatable: true,
                selectable: 'row',
                filterable: true,
                sortable: true,
                resizable: true,
                scrollable: { virtual: true },
                detailInit: acctDetailInit,
                height: getHeight(),
                detailExpand: function() { resizeVirtualScroll(); },
                detailCollapse: function () { resizeVirtualScroll(); },
                columns: [
                    { field: "id", filterable: false, width: 65, },
                    { field: "name", title: "Name" },
                    { field: "aum", title: "Current Value", format: "{0:C}", attributes: { style: "text-align:right;" } }
                ]
            });
        });
 
        // datasource
        var aumData = new kendo.data.DataSource({
            pageSize: 100,
            sort: { field: "name", dir: "asc" },
            transport: {
                read: {
                    url: '<%= Common.GetAppSetting( "WebApiBaseUrl" ) %>Portfolio/Clients/Value',
                    dataType: "json",
                    beforeSend: function(req) {
                        req.setRequestHeader("Authorization", "Session <%= Common.WebApiToken %>");
                    }
                }
            },
            schema: {
                model: {
                    fields: {
                        id: { type: "number" },
                        name: { type: "string" },
                        value: { type: "number" }
                    }
                }
            },
            errors: function(e) {
                console.log(e.errors);
            }
        });
 
        // detail grid and datasource
        function acctDetailInit(e) {
            $("<div/>").appendTo(e.detailCell).kendoGrid({
                dataSource: {
                    transport: {
                        read: {
                            url: '<%= Common.GetAppSetting( "WebApiBaseUrl" ) %>Portfolio/Clients/' + e.data.id + '/Accounts/Value',
                            dataType: "json",
                            beforeSend: function(req) {
                                req.setRequestHeader("Authorization", "Session <%= Common.WebApiToken %>");
                            }
                        }
                    }
                },
                detailExpand: function(e) {
                    console.log(e.masterRow, e.detailRow);
                     
                },
                navigatable: true,
                selectable: 'row',
                filterable: true,
                sortable: true,
                scrollable: false,
                resizable: true,
                columns: [
                    { field: "id", filterable: false, width: 65, },
                    { field: "name", title: "Account" },
                    { field: "aum", title: "Current Value", format: "{0:C}", attributes: { style: "text-align:right;" } }
                ]
            });
        }
0
Vladimir Iliev
Telerik team
answered on 03 Jul 2013, 10:16 AM
Hi Dustin,

 
Basically the solution that I provide with my previous reply is a custom one and you can use it as a baseline to achieve the desired behavior. In current case you can use for example the setTimeout method to execute the provided code after the current expand / collapse is fully completed. 

Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Dustin
Top achievements
Rank 2
answered on 03 Jul 2013, 03:04 PM
I would try the setTimeout as a workaround, but depending on the user, the amount of data coming back can be greatly different and take longer. I would hate to have to put a huge delay, which in the end may not be long enough at times.

I wrote a custom solution on my own, which I thought would work, but when I expand enough items (in my scenerio about 3000px of expanded detail grids) then scroll down, my Chrome browser would throw an error and need to refresh the page.

This code stores the height of the detail grid the first time it is loaded and since the event on dataBound is after it is expanded, the virtual scrollbar height can be changed right then. On subsequent expands, since the detailExpand event fires off before the detail grid has its height, I had to use the stored height from the first expansion.

So this code almost works other than Chrome dying on me after large amounts are expanded.
//resize logic
           $(window).trigger(
'resize');
 
        function getHeight() {
            return $(window).height() - 100 - $('.CustomHeader').height();
        }
 
        function resizeGrid(args) {
            $('#grid').height(getHeight());
            var gridElement = $("#grid"),
                dataArea = gridElement.find(".k-grid-content:first"),
                gridHeight = gridElement.innerHeight(),
                otherElements = gridElement.children().not(".k-grid-content:first"),
                otherElementsHeight = 0;
 
            otherElements.each(function () {
                otherElementsHeight += $(this).outerHeight();
                });
            dataArea.height(gridHeight - otherElementsHeight);
            return args;
        }
 
        $(window).resize(function() {
            resizeGrid();
        });
 
        function resizeVirtualScroll(firstTime, expand) {
            var grid = $("#grid").data("kendoGrid");
 
            // on initial load this will fire off and be null
            if (grid == null) return;
             
            // when expanding for first time, the expand event will kick off then the databound
            if ($(grid.select()).attr("data-height") == null && !firstTime) return;
 
            var detailHeight = 0;
            var newHeight = $(".k-grid-content div table").height();
            console.log("grid height:" + newHeight);
             
            if (firstTime) {
                detailHeight = $(grid.select()).next(".k-detail-row").children(":first").height();
                console.log("detail height:" + detailHeight);
                $(grid.select()).attr("data-height", detailHeight);
                 
            } else {
                //get selected row data height
                detailHeight = parseFloat($(grid.select()).attr("data-height"));
                console.log("detail height:" + detailHeight);
                 
                if (expand) {
                    newHeight += detailHeight;
                } else {
                    newHeight -= detailHeight;
                }
            }
             
            console.log("final height:" + newHeight);
 
            var bar = $(".k-scrollbar.k-scrollbar-vertical div");
            bar.height(newHeight);
        }
 
 
        // setup grid
        $(document).ready(function() {
 
            $("#grid").kendoGrid({
                dataSource: aumData,
                navigatable: true,
                selectable: 'row',
                filterable: true,
                sortable: true,
                resizable: true,
                scrollable: { virtual: true },
                dataBound: resizeGrid,
                detailInit: acctDetailInit,
                height: getHeight(),
                detailExpand: function() { resizeVirtualScroll(false, true); },
                detailCollapse: function () { resizeVirtualScroll(false, false); },
                columns: [
                    { field: "id", filterable: false, width: 65, },
                    { field: "name", title: "Name" },
                    {
                        field: "aum", title: "Current Value", format: "{0:C}", attributes: { style: "text-align:right;" }, width: 120,
                        headerAttributes: {
                            style: "text-align: right;"
                        }
                    }
                ]
            });
        });
 
        // datasource
        var aumData = new kendo.data.DataSource({
            pageSize: 300,
            sort: { field: "name", dir: "asc" },
            transport: {
                read: {
                    url: '<%= Common.GetAppSetting( "WebApiBaseUrl" ) %>Portfolio/Clients/Value?usedOnly=1',
                    dataType: "json",
                    beforeSend: function(req) {
                        req.setRequestHeader("Authorization", "Session <%= Common.WebApiToken %>");
                    }
                }
            },
            schema: {
                model: {
                    fields: {
                        id: { type: "number" },
                        name: { type: "string" },
                        value: { type: "number" }
                    }
                }
            },
            errors: function(e) {
                console.log(e.errors);
            }
        });
 
        // account level detail grid
        function acctDetailInit(e) {
            $("<div/>").appendTo(e.detailCell).kendoGrid({
                dataSource: {
                    sort: { field: "name", dir: "asc" },
                    transport: {
                        read: {
                            url: '<%= Common.GetAppSetting( "WebApiBaseUrl" ) %>Portfolio/Clients/' + e.data.id + '/Accounts/Value?usedOnly=1',
                            dataType: "json",
                            beforeSend: function(req) {
                                req.setRequestHeader("Authorization", "Session <%= Common.WebApiToken %>");
                            }
                        }
                    }
                },
                detailExpand: function(e) {
                    console.log(e.masterRow, e.detailRow);
                     
                },
                navigatable: true,
                selectable: 'row',
                filterable: true,
                sortable: true,
                scrollable: false,
                dataBound: function(e) {
                    resizeVirtualScroll(true, true);
                },
                resizable: true,
                columns: [
                    { field: "id", filterable: false, width: 65, },
                    { field: "name", title: "Account" },
                    { field: "number", title: "Account #" },
                    { field: "managementStyle", title: "Management Style" },
                    {
                        field: "value", title: "Current Value", format: "{0:C}", attributes: { style: "text-align:right;" }, width: 120,
                        headerAttributes: {
                            style: "text-align: right;"
                        }
                    }
                ]
            });
        }
0
Vladimir Iliev
Telerik team
answered on 08 Jul 2013, 11:05 AM
Hi Dustin,

 
Please note that supporting custom solutions is out-of-scope of our support service as it covers the build-in functionality of the controls only. If you'd like to receive custom code from Telerik, I would suggest to check our premium services.

Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tags
Grid
Asked by
Joel
Top achievements
Rank 1
Answers by
Joel
Top achievements
Rank 1
Dustin
Top achievements
Rank 2
Vladimir Iliev
Telerik team
Share this question
or