How do I scroll an ngGrid to show the current selection?

All we need is an easy explanation of the problem, so here it is.

I’m setting the selection of my ngGrid from JavaScript, calling gridOptions.selectItem(). I have multiSelect set to false, so there is only ever one row selected. I’d like the ngGrid to automatically scroll to show the newly selected row, but I don’t know how to do this: can anyone help, please?

On a related topic: can I disable row selection by mouse click? If so, how?

Edited to add

I’d also like to disable keyboard navigation of the selected row, if possible.

What worked:

AardVark71’s answer worked. I discovered that ngGrid defines a property ngGrid on the gridOptions variable which holds a reference to the grid object itself. The necessary functions are exposed via properties of this object:

$scope.gridOptions.selectItem(itemNumber, true);
$scope.gridOptions.ngGrid.$viewport.scrollTop(Math.max(0, (itemNumber - 6))*$scope.gridOptions.ngGrid.config.rowHeight);

My grid is fixed at 13 rows high, and my logic attempts to make the selected row appear in the middle of the grid.

I’d still like to disable mouse & keyboard changes to the selection, if possible.

What also worked:

This is probably closer to the ‘Angular Way’ and achieves the same end:

// This $watch scrolls the ngGrid to show a newly-selected row as close to the middle row as possible
$scope.$watch('gridOptions.ngGrid.config.selectedItems', function (newValue, oldValue, scope) {
            if (newValue != oldValue && newValue.length > 0) {
                var rowIndex = scope.gridOptions.ngGrid.data.indexOf(newValue[0]);
                scope.gridOptions.ngGrid.$viewport.scrollTop(Math.max(0, (rowIndex - 6))*scope.gridOptions.ngGrid.config.rowHeight);
            }
        }, true);

although the effect when a row is selected by clicking on it can be a bit disconcerting.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

It sounds like you can make use of the scrollTop method for the scrolling.

See also http://github.com/angular-ui/ng-grid/issues/183 and the following plunker from @bryan-watts http://plnkr.co/edit/oyIlX9?p=preview

An example how this could work would be as follows:

function focusRow(rowToSelect) {
  $scope.gridOptions.selectItem(rowToSelect, true);
  var grid = $scope.gridOptions.ngGrid;
  grid.$viewport.scrollTop(grid.rowMap[rowToSelect] * grid.config.rowHeight);
}

edit:

For the second part of your question “disabling the mouse and keyboard events of the selected rows” it might be best to start a new Question. Sounds like you want to set your enableRowSelection dynamically to false? No idea if that’s possible.

Method 2

I believe I was looking for the same behavior from ng-grid as yourself. The following function added to your gridOptions object will both disallow selection via the arrow keys (but allow it if shift or ctrl is held down) and scroll the window when moving down the list using the arrow keys so that the currently selected row is always visible:

beforeSelectionChange: function(rowItem, event){
    if(!event.ctrlKey && !event.shiftKey && event.type != 'click'){
      var grid = $scope.gridOptions.ngGrid;
      grid.$viewport.scrollTop(rowItem.offsetTop - (grid.config.rowHeight * 2));
      angular.forEach($scope.myData, function(data, index){
        $scope.gridOptions.selectRow(index, false);
      });
    }
    return true;
  },

edit: here is a plunkr:
http://plnkr.co/edit/xsY6W9u7meZsTJn4p1to?p=preview

Hope that helps!

Method 3

I found the accepted answer above is not working with the latest version of ui-grid (v4.0.4 – 2017-04-04).

Here is the code I use:

$scope.gridApi.core.scrollTo(vm.gridOptions.data[indexToSelect]);

In gripOptions, you need to register the gridApi in onRegisterApi.

onRegisterApi: function (gridApi) {
   $scope.gridApi = gridApi;
},

Method 4

  var grid = $scope.gridOptions.ngGrid;
    var aggRowOffsetTop = 0;
    var containerHeight = $(".gridStyle").height() - 40;
    angular.forEach(grid.rowFactory.parsedData, function(row) {
        if(row.entity.isAggRow) {
            aggRowOffsetTop = row.offsetTop;
        }
        if(row.entity.id == $scope.selectedId) {
            if((row.offsetTop - aggRowOffsetTop) < containerHeight) {
                 grid.$viewport.scrollTop(aggRowOffsetTop);
            } else {
                grid.$viewport.scrollTop(row.offsetTop);
            }
        } 
    });

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply