Friday, September 5, 2014

Programmatically scroll to selected row in Kendo UI Grid widget (using AngularJS)

I had successfully selected a row programmatically in Kendo UI - AngularJS. But because I usually refreshed the data for the Kendo UI Grid, occasionally the selected row would be "scrolled out". So yes, the row was selected, but the user still needed to scroll down to see it.

This was done by using jQuery's scrollTop() method.


  1. First thing we need to do is somehow to get a reference to the Kendo's Grid widget. 
  2. Then we need to get the vertical distance between the Grid "content area" and the selected row.
  3. Finally we call scrollTop() to scroll the grid the above distance.


1. Get a reference to the Kendo's Grid widget
This is very simple.
<div kendo-grid="theGrid"
     k-options="portfolioGridConfig"
     k-data-source="portfolioData"
     k-height="400"
     k-on-change="onUserSelectRow(dataItem)"></div>

Simply specify the variable name in the kendo-grid attribute. Then a simple:
$scope.theGrid
will reference the Kendo widget. Simply simple.


2. get the vertical distance between the Grid "content area" and the selected row
This is done using the offset() jQuery method of the Grid and the selected row. Obtaining the jQuery object of the selected row is outside the scope of this article. I talked about it in a previous post, so you can go take a look. It looks like this:
var row = $('[data-uid=' + item.uid + ']');

Getting the vertical offset of the row from the top of the document then looks like this:
row.offset().top

Now for the vertical offset of the Grid's content area. Looking at the Kendo Grid API, I see that there is a content property "which represents the grid content element, which holds the scrollable content". That's what we want. The vertical offset of the "Grid content element" is then:
$scope.theGrid.content.offset().top

And the vertical difference is just the difference:
row.offset().top - $scope.theGrid.content.offset().top

3. call scrollTop()
Nothing special here. Except if you do a lot of async calls to populate the Grid content. If so, you might find that the Grid content has already been scrolled down. So to be safe, we scroll the Grid content all the way up, then we scroll it back down to the selected item.
var row = $('[data-uid=' + item.uid + ']');

$scope.theGrid.content.scrollTop(0); // we HAVE to reset the scroll first.
$scope.theGrid.content.scrollTop( row.offset().top - $scope.theGrid.content.offset().top );

Conclude
Surely someday Kendo - AngularJS will have a method to do this without resorting to "behind the back" jQuery code. Sooner or later, we'll be free, to leave this all behind. Sooner or later, this is gonna be, the last thing on my mind.

The jQuery docs for scrollTop() and offset() are here.

2 comments:

  1. Thanks fella for this useful hint.
    Althought I dont use Angular JS (I am using KnockoutJS with Telerik products), I implemented this trick into my code :)
    I hope -like you did- that a day Telerik will add this feature in its own code.

    ReplyDelete
  2. Thanks a lot for the great workaround ... it surely helped a lot ...

    ReplyDelete