Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scroll to selection in Angular ui-grid (not ng-grid)

For my Angular JS grid work, I'm using ui-grid rather than ng-grid as ui-grid is meant to be the new version which is purer Angular.

I've got a grid that I'm populating with a http response, and I'm able to select a row (based on finding the record matching a $scope variable value) using the api.selection.selectRow method call.

What I need to do next is scroll the grid to that record.

There's an existing stack overflow question along the same lines that is for ng-grid and the answer to that refers to undocumented features which are not present in ui-grid so I can't use that approach.

The closest I've got is finding $scope.gridApi.grid to get a reference to the actual grid itself but looking through the properties and methods in the Chrome debugger doesn't show anything that sounds like it could work.

like image 374
Chris Rothery Avatar asked Oct 11 '14 15:10

Chris Rothery


2 Answers

You can use the cellNav plugin. You should already have a reference to your row entity from the selection. The documentation is here.

gridApi.cellNav.scrollTo(grid, $scope, rowEntity, null);
like image 155
Tom Avatar answered Nov 03 '22 18:11

Tom


I managed to hack together something that works pretty well but it's a bit dodgy and could probably be cleaner with a bit more Angular/jquery understanding.

I used the browser dom explorer to find that the scrollbars have a css class that we can detect to find them and then set the scroll properties on them to have the grid scroll (the grid and scrollbars are separate divs but their properties are bound so changing one updates the other).

It doesn't completely work for scrolling to the last row of the grid. This could be a timing issue, I've noticed when using breakpoints that the grid comes on screen a little larger and then shrinks down to it's final size. This could be messing with the scrolling values.

The first loop finds the height of the grid by adding up the rows, and the y position of the row for my data object (project), then we find the scrollbar and set it's scrollTop, trying to centre the row on screen without going out of bounds.

var grid = $scope.projectsGridApi.grid;
// var row = grid.rowHashMap.get(project.$$hashKey);

var found = false;
var y = 0;
var totalY = 0;
var rowHeight = 0;
for (var rowIdx in grid.rows)
{
    var row = grid.rows[rowIdx];
    if (row.entity.$$hashKey == project.$$hashKey)
    {
        found = true;
        rowHeight = row.height;
    }

    if (!found)
    {
        y += row.height;
    }
    totalY += row.height;
}

// now find the scroll bar div and set it's scroll-top 
// (todo: checking if we're at the end of the list - setting scrollTop > max means it doesn't work properly
var grid = $scope.projectsGridApi.grid;


// annoyingly this is nastily coded to find the scrollbar and isn't completely right
// I think the grid is a little taller when this is called, then shrinks 
// which affects what the maximum is (so we might not always be able to put the selected item on screen if it is the last one).

var holderDiv = $('#projectsGridHolder');
if (holderDiv)
{
    var scrollBarDivs = holderDiv.find('.ui-grid-native-scrollbar');
    if (scrollBarDivs)
    {
        for (var scrollBarDivIdx in scrollBarDivs)
        {
            var scrollBarDiv = scrollBarDivs[scrollBarDivIdx];                        

            var scrollBarDivClass = scrollBarDiv.className;
            if (scrollBarDivClass)
            {
                if (scrollBarDivClass.indexOf('vertical') != -1)
                {   
                    var scrollHeight = scrollBarDiv.scrollHeight;
                    var clientHeight = scrollBarDiv.clientHeight;

                    if (rowHeight > 0)
                    {
                        y -= (clientHeight - rowHeight) / 2; // center on screen be scrolling slightly higher up
                    }
                    if (y < 0) y = 0;
                    else if (y > totalY - clientHeight) y = totalY - clientHeight;

                    scrollBarDiv.scrollTop = y;
                }
            }
        }
    }
}
like image 20
Chris Rothery Avatar answered Nov 03 '22 19:11

Chris Rothery