Grid with virtual scrolling - scroll to row

1 Answer 1001 Views
Grid
syian
Top achievements
Rank 1
Veteran
syian asked on 15 Sep 2021, 02:00 PM

I am trying to find a way to scroll to a specific row while using virtual scrolling but my solution has not been consistent. Here is the function that is being called each time I want to select a specific row:

function selectGridRow(grid_element,grid_value,grid_field) {
	var dataSource = grid_element.dataSource,
            filters    = dataSource.filter() || {},
	    sort       = dataSource.sort() || {},
	    models     = dataSource.data();
		
	var query         = new kendo.data.Query(models),
            rowNum        = 0,
	    modelToSelect = null;
	
	models = query.filter(filters).sort(sort).data;
	
	// Item Position
	for (var i = 0; i < models.length; ++i) {
		var model = models[i];
		if (model[grid_field] == grid_value) {
			modelToSelect = model;
			rowNum = i;
			break;
		}
	}
	
	grid_element._selectedIds = {}; 
	
        // Change to the page where the row is and select it
	var currentPageSize = grid_element.dataSource.pageSize(),
	    pageWithRow     = parseInt((rowNum / currentPageSize)) + 1; 
	
	grid_element.dataSource.page(pageWithRow);
	
	var row = grid_element.element.find("tr[data-uid='" + modelToSelect.uid + "']");
	
	if (row.length > 0) {
	   grid_element.select(row);
	   grid_element.content.scrollTop(grid_element.select().position().top);  
        }
}

While the above function sometimes works fine, finds the row and also scrolls to it, other times this fails. For example, when a row at the very top is selected and I am trying to select a row at the very bottom, I can see grid changing page but the row is not getting selected.

Is there anything I am missing here?

1 Answer, 1 is accepted

Sort by
0
Georgi Denchev
Telerik team
answered on 20 Sep 2021, 07:48 AM

Hi, Syian,

Thank you for the provided code snippet.

When the Grid is paged or virtual scrolling is enabled, only the rows on the current page(or up to the currently scrolled position) are rendered. My guess is that you're attempting to select a row which is not yet rendered.

In this case you could modify the internal collection of selected ids, instead of using the select() method which selects a row based on the rendered element.

Example:

grid_element._selectedIds[modelToSelect.id] = true;
// It is not always necessary to refresh, however it might be needed in certain scenarios. For example if you try to select a row that is already visible(has already been rendered).
grid._element.refresh();

Please note that only one of the 2 options should be selected a time. You can either use Virtual Scrolling or Paging, using both at the same time could lead to issues. This is mentioned in the Documentation for Virtual Scrolling.

Let me know if you have any questions.

Best Regards,
Georgi Denchev
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

syian
Top achievements
Rank 1
Veteran
commented on 20 Sep 2021, 11:55 AM

Hi Georgi, 

thank you for the explanation.

That was my assumption as well, that the row was not yet rendered. What do you mean by modify the internal collection of selected ids? Is it something I should try in the function I provided? Could you please provide a more conrete example with a dojo?

Thank you in advance,
Syian

Georgi Denchev
Telerik team
commented on 20 Sep 2021, 12:38 PM

Hi, Syian,

Based on the provided code snippet, you just need to replace the select() method with the code from above:

	if (row.length > 0) {
           /* This goes away */
	  // grid_element.select(row);
         
           /* This comes in it's place */
           grid_element._selectedIds[modelToSelect.id] = true;
           grid_element.refresh();

           /* This remains the same */
	   grid_element.content.scrollTop(grid_element.select().position().top);  
        }

Let me know how it goes.

syian
Top achievements
Rank 1
Veteran
commented on 20 Sep 2021, 02:16 PM

Hi Georgi, 

thank you for the prompt reply.

I tried out the example you provided, and I have noticed that even though in some cases it works fine, the following can also happen:

  1. If the row is not visible at the beginning, but then gets correctly selected and the grid scrolls to it, when I scroll further down it takes me back to the very top and loses sight of the selected row
  2. In some cases it does not scroll to the selected row. It selects the right row and scrolls until a specific point, but not until the row is visible

Here is an example of how the grid was implemented in case it helps you: 

jq(document).ready(function() {
    var grid_dataitem,
        grid_counter = 0; 

    jq("grid").kendoGrid({                                                                             
        autoBind: false,                                                                                                          
        dataSource: datasource_grid,
        toolbar: [                                                                                                               
            { template: kendo.template(jq("#grid_toolbar").html()) }                                                         
        ],                                                                                                                     
        height: height,
        pageable: {                                                                                                              
            previousNext:   false,                                                                                                 
            numeric:        false,                                                                                                 
            messages: {                                                                                                           
                display: "contains: {2}",                                                                                 
                empty: "no records to show"                                                                                        
            }                                                                                                                     
        },           
        scrollable: {
            virtual: true                                                                                                          
        },                                                                                                                        
        columns: [
            { ... },                                                       
            { command: [                                                                                                      
                {                                                                                                             
                    name: "delete",                                                                                        
                    template: "<a class=k-button k-grid-delete><span class=k-icon k-i-delete></span></a>",             
                    click(e){                                                                                                 
                        onclick_delete();                                                                                    
                    }                                                                                                         
                }                                                                                                             
            ] }                                                                                                               
        ],     
        sortable: true,                                                                                                             
        navigatable: true,                                                                                                            
        selectable: true,                                                                                                             
        noRecords: true,                                                                                                             
        messages: {                                                                                                           
            noRecords: "no records to show",                                                                                     
        },                                                                                                                           
        change: function(e) {                                                                                                            
            var selectedRows = this.select(),                                                                                  
                dataItem     = this.dataItem(selectedRows[0]);                                                                 

            if((dataItem !== null) && (dataItem !=  grid_dataitem)) {                                                
                grid_dataitem = dataItem;                                                                            
                e.sender._selectedIds = {};                                                                                  
                e.sender._selectedIds[dataItem.field1] = true;                                                                  

                ...
            }                                                                                                                 
        },                                                                                                                               
        persistSelection: true,                                                                                                           
        dataBound: function(e) {
            if (grid_counter == 0) {                                                                                           
                this.select("tr:eq(0)");                                                                                       
                grid_counter++;                                                                                      
            }                                                                                                                 

            ...
        }
    });                                                                                                                       
});

I am looking forward to your answer. 

Thanks,
Syian

Georgi Denchev
Telerik team
commented on 23 Sep 2021, 10:08 AM

Hi, Syian,

Thank you for the additional details.

Please accept my apologies, but there seems to have been misunderstanding, perhaps I didn't explain properly. The solution that I provided was meant to help solve the problem with the row not getting selected, however scrolling to a specific row is not possible when Virtualization is enabled.

This is also described in the Known Limitations section:

  • Programmatic scrolling to a particular Grid row is not supported when virtual scrolling is enabled, because it is not possible to reliably predict the exact scroll offset of the row.

While it's true that you can scroll through the initially rendered rows(as demonstrated in this dojo), scrolling any further would lead to problems as the rows are rendered on demand and the calculation for the distance becomes incorrect.

 

Tags
Grid
Asked by
syian
Top achievements
Rank 1
Veteran
Answers by
Georgi Denchev
Telerik team
Share this question
or