angular-ui / ui-grid

UI Grid: an Angular Data Grid
http://ui-grid.info
MIT License
5.39k stars 2.47k forks source link

Request: Dynamic height based on row count #1735

Open joshmackey opened 9 years ago

joshmackey commented 9 years ago

At the moment we solve this by changing the container height based on the number of rows in the grid but it would be nice to be able to tell ui-grid to not be constrained by a specific height so that all rows are visible without the grid itself having to scroll (its fine if the page needs to be scrolled).

While this can be done by setting the container height to something massive, it leaves lots of bordered whitespace which looks bad.

c0bra commented 9 years ago

In 3.0 you can set the minRowsToShow property and the grid will automatically resize itself to display that number of row, assuming the element itself has no defined height.

An add-on feature that just resizes the grid to show all of its rows and not would be very fairly easy, and has been requested a couple times, but there's doesn't seem to be anyone interested in actually putting in the time to develop it. It will probably get done once higher priority items get checked off.

joshmackey commented 9 years ago

Yes but minRowsToShow can only be set once and you get a lot of empty whitespace if you don't actually have that many rows.

I already wrote a resizer based on the number of rows but it just seems highly inefficient.

c0bra commented 9 years ago

If the number of rows keeps changing and you want the grid to adjust for that, how would you get away from having to resize the element every time? On Oct 6, 2014 5:23 PM, "Josh Mackey" notifications@github.com wrote:

Yes but minRowsToShow can only be set once and you get a lot of empty whitespace if you don't actually have that many rows.

I already wrote a resizer based on the number of rows but it just seems highly inefficient.

— Reply to this email directly or view it on GitHub https://github.com/angular-ui/ng-grid/issues/1735#issuecomment-58109573.

joshmackey commented 9 years ago

Well, as long as a specific height isn't set, the element should just keep growing. The problem is that it keeps growing into a specific height container, thus scrollbars.

PaulL1 commented 9 years ago

I think the only way to do this would be to have a resizer based on the number of rows - there's no other way to know how large the grid should be made.

There could be value in having this part of the grid, in that the grid already knows how high rows are. I'd imagine it would need to do something like:

Presumably the containing element would automatically grow if this were done.

I think this is plausible, but I wouldn't underestimate how much work it is.

mburbea commented 9 years ago

I have a similar issue. I have filterable data with a functional footer, and this leads to nasty whitespace when the search is used and reduces the size to less than the container. Ideally the grid should respect a min-height and max-height attribute and scroll when needed. And what would be nice is simply to paint filler rows (e.g. just keep zerbra striping) when there is no data. I wouldn't mind having 5 rows added if the filtered set is less than the min-height.

Manduro commented 9 years ago

@joshmackey Would you mind sharing your code for doing this?

joshmackey commented 9 years ago

@Manduro

Its quite crude but here you are.

This gets called whenever the rows in the grid change.

function setHeight(extra) {
      $scope.height = (($scope.gridOptions.data.length * 30) + 30);
      if (extra) {
        $scope.height += extra;
      }
      $scope.api.grid.gridHeight = $scope.height;
    }

And this is on the div ui-grid-auto-resize ng-style="{ 'height': height }"

I basically just resize the container based on the number of rows (plus the header) and allow auto-resize to handle the rest.

BrodaUa commented 9 years ago

Hi guys, I have a similar problem. I wanna set the height of my grid so it would be display all my rows, and I use the next code: $scope.gridOptions.minRowsToShow = $scope.gridOptions.data.length ; where 'data' is my array of objects that are displayed. But ~data.length does not return the amount of my objects, is there are something wrong in my code? Or I can`t do that?

PaulL1 commented 9 years ago

It depends on how you're doing it. If you are retrieving the data via http, then likely gridOptions.data.length is zero at the time the code runs. If you are setting gridOptions.data = 'data';, then you actually need to use $scope.data.length. I'd need to see more of your code to be sure, but the easy way is to set a breakpoint at the time that this code runs, and check what's in gridOptions.data at that point in time.

BrodaUa commented 9 years ago

Here code of my controller: app.controller('SimpleController', ['$scope', '$http', function ($scope, $http) {

$scope.gridOptions = { enableRowHeaderSelection: false };

$scope.gridOptions.columnDefs = [
   { name: 'id' },
   { name: 'name' },
   { name: 'age' },
   { name: 'address.city' },
   { name: 'gender' }
];
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
    .success(function (data) {
        $scope.gridOptions.data = data;
    });
$scope.gridOptions.minRowsToShow = $scope.gridOptions.data.length;
$scope.gridOptions.enableHorizontalScrollbar = false;
$scope.gridOptions.enableVerticalScrollbar = false;

}]); But I still can`t get the data.length :(

PaulL1 commented 9 years ago

The data has no length until the $http promise resolves. You could move the minRows into the http response, but that may be too late.

Sent from my iPhone

On 25 Nov 2014, at 9:21 pm, BrodaUa notifications@github.com wrote:

Here code of my controller: app.controller('SimpleController', ['$scope', '$http', function ($scope, $http) {

$scope.gridOptions = { enableRowHeaderSelection: false };

$scope.gridOptions.columnDefs = [ { name: 'id' }, { name: 'name' }, { name: 'age' }, { name: 'address.city' }, { name: 'gender' } ]; $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json') .success(function (data) { $scope.gridOptions.data = data; }); $scope.gridOptions.minRowsToShow = $scope.gridOptions.data.length; $scope.gridOptions.enableHorizontalScrollbar = false; $scope.gridOptions.enableVerticalScrollbar = false; }]); But I still can`t get the data.length :(

— Reply to this email directly or view it on GitHub.

BrodaUa commented 9 years ago

If I try to do something like that: $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json') .success(function (data) { $scope.gridOptions.minRowsToShow = data.length; //or after grid.Options=data $scope.gridOptions.data = data; // $scope.gridOptions.minRowsToShow = data.length; }); then it runs like if I didn`t write this : " $scope.gridOptions.minRowsToShow = data.length; ". The length stay by default - 10 rows.

aidanlister commented 9 years ago

+1 I don't need scroll bars, I just want my grid to take as much room as it needs.

dennistang commented 9 years ago

+1 to this, don't need this to scroll at all.

cwbuecheler commented 9 years ago

Please consider this another request for the grid's container element to just grow as tall as it needs to be to fit all the content. I don't need scrollbars either.

brunobodson commented 9 years ago

+1, would be nice to be able to show all rows without a scrollbar

amuste commented 9 years ago

+1, I need this enhancement too

henry74 commented 9 years ago

+1

iblecher commented 9 years ago

+1

pascaloliv commented 9 years ago

+1 ! Greatly appreciated!

steven-bowdridge commented 9 years ago

+1

adoming3 commented 9 years ago

+1

adoming3 commented 9 years ago

Sorry to jack the thread. Here's my work around for anyone trying to make a grid dynamic height based upon visible rows.

        $scope.getTableStyle= function() {
            var marginHeight = 20; // optional
            var length = $('img:visible').length; // this is unique to my cellTemplate
            return {
                height: (length * $scope.gridOptions.rowHeight + $scope.gridOptions.headerRowHeight + marginHeight ) + "px"
            };
        };
<div ui-if="gridOptions.data.length>0" id="grid1" ui-grid="gridOptions" class="grid" ui-grid-pagination ui-grid-auto-resize ng-style="getTableStyle()"></div>
trance4mation commented 9 years ago

+1

steven-bowdridge commented 9 years ago

@adoming3, this worked for me. I had to set gridOptions.minRowsToShow to 999, but now the table height is matching just the visible rows. Thank you.

ghost commented 9 years ago

+1

mparisi76 commented 9 years ago

+1

alderaDev commented 9 years ago

+1

PaulL1 commented 9 years ago

There seem to be a lot of +1s being added. Any of those people keen to provide a PR that adds the functionality?

cwbuecheler commented 9 years ago

EDIT: this css fix can in some cases break the grid. Removing it until I can troubleshoot.

mikechabot commented 9 years ago

+1 - this seems like basic functionality.

PaulL1 commented 9 years ago

Perhaps I should be clearer. Putting "+1" on this thread isn't going to achieve anything. Doing this is far more complicated than people seem to be imagining, so the only ways this would get done would be for someone to sit down and write the code themselves and submit a PR with that code, or pay some sort of bounty for one of the regular contributors to work through all the complexity associated with it. One of the key aims of ui.grid is row virtualisation, and providing what is suggested in this request would basically bypass all the row virtualisation - in short ui.grid is heavily based around scrolling as a key feature.

cwbuecheler commented 9 years ago

I'd love to put in some code but I'm slammed for time and I'm also not an angular expert -- still learning -- so I fear I'm not the best option. Interior scrollbars really don't work for my project so that's why I initially added a +1, and also tried (and failed) to come up with a CSS-based fix. What happened was: my grid would only render four rows, because it seems to base the number of rows it chooses to render off of the height of an interior div?

I'm curious: what's the value in having to scroll within the grid container? I'm not trying to be a jerk at all, I'd just like to understand better -- I don't precisely know what row virtualisation means or why it's valuable (or why it requires scrollbars). The browser already has a scrollbar, and web pages are generally accepted as being able to grow vertically. What's gained by locking the grid's container height?

ghost commented 9 years ago

@PaulL1 valid point, but without +1's it would be inpossible to express user's opinion on the matter and draw attention of someone who can make a contribution. Usually people tend to check first if the feature is needed by someone else, and it is nearly impossible to expect appearance of feature that does not show a clear sign of necessity, that can be measured objectively. Since GitHub is apparently not offering any other way to express the will to have the feature, +1 is a natural and in fact only way to do so.

PaulL1 commented 9 years ago

@cwbuecheler: the key reasoning behind ui.grid is to deal with large data sets without unreasonable browser overhead. When you generate a very large DOM (think thousands of rows), it puts a lot of load on the browser. With row virtualisation (and therefore, implicitly, with scrolling) the grid only renders those DOM elements that are actually visible. When you scroll the grid we are behind the scenes creating and destroying DOM elements (well, actually we reuse the existing ones) to provide the illusion you're scrolling through a huge list of data that is all rendered and waiting for you.

Once we go to showing a flat list of everything we'd be bypassing all this logic, and to some extent what we'd then have is just a glorified ng-repeat. Certainly before the project became as full-featured that would have made little sense - it'd be easier to just have an ng-repeat without the overhead that ui-grid adds. I guess now that we have features like exporter, importer, sorting, filtering etc, it may make more sense to use ui.grid in that way, but it certainly isn't the design direction of the project.

We do have some work kicking off around sizing, as we don't particularly like elements of our current sizing code. If things go well with that it may open up opportunities to make the grid sizing more dynamic, which would address some issues with making the grid (more) responsive, but might also provide some hooks into doing this.

cwbuecheler commented 9 years ago

@PaulL1 - got it, thanks. That explains what you mean by row virtualisation and yes, that makes tons of sense from an overhead perspective. I think the thing is: a lot of people are looking to do what I'm doing: displaying about 50-100 rows, with paging, where each new page hits the server, so front-end overhead ends up not being much of a concern. I agree that's basically a glorified ng-repeat, but it's the sorting and paging stuff that most people don't want to go to the trouble of trying to write themselves (I actually found ui-grid because I was considering writing sorting for my own repeater, but was hoping to find a faster, easier solution than DIY).

Very much appreciate the quick and thorough response. Cheers!

PaulL1 commented 9 years ago

If you went with a native repeater you'd get away also from our limitation on fixed row height - that limitation largely exists so we can calculate the scroll. So your use case would relax a bunch of limitations that drive some of the ui.grid behaviour.

If you are OK with a fixed row height, and you know your page size, could you perhaps set your grid height to the row height * page size, and then resize the grid height when your data arrives if it's less than a full page? In theory that would work, and most of the time would involve very little resizing.

PaulL1 commented 9 years ago

I merged #3069 today, and given the discussion on this issue, I wondered if a similar approach could be used to set the grid height to the # rows * row height. Someone may want to try that.

plantwebdesign commented 9 years ago

I think a simple fix is to amend the height of the .ngViewPort div at the point when the row data is replaced?

$('.ngViewport').height(scope.rowData.length * scope.gridOptions.rowHeight)

Maybe I am missing something...

double3 commented 9 years ago

+1

maxcc0 commented 9 years ago

Here's what I'm doing, using a watcher to watch change in visible rows using getVisibleRows() from the gridApi and whenever it changes, I calculate grid height which is [math.min(#rows, maxrows)*gridRowHeight + gridheaderheight + grid footer height + 20]

--maxrows for me is 8, so if visible rows is 25, I want the grid height to be calculated based on maxrows so that I can get a vertical scrollbar --20 is for the horizontal scrollbar

This gives me dynamic height. When I change page and there is only one row to show, grid height adjusts (no whitespace)... however the change in height is not as seamless as I want it to be...I'm seeing the pagination footer slightly jumping before it comes to the correct position... I'm sure there is a better way, suggestions anyone??

fauverism commented 9 years ago

+1

nhducit commented 9 years ago

+1 I need this feature too

viros commented 9 years ago

I can't understand why to fix that requires so much efforts? I would suggest add an option do not calculate height at all. I'm trying to fix this in css: .ui-grid-viewport, .ui-grid-canvas{ height: auto !important; } It works fine till i do not use paging. If i use this 'trick' and paging than it renders wrong numbers of rows. If you can fix that, than it will be amaizing.

viros commented 9 years ago

Next solution works for me: css: .ui-grid-viewport, .ui-grid-canvas{ height: auto !important; }

on pageSize changed i set next options: gridOptoins.minRowsToShow = pageSize; gridOptoins.virtualizationThreshold = pageSize;

brunobodson commented 9 years ago

The solution of @viros works for me as well, but disables scrolling down when mouse is hovering over the grid, or is it just me?

viros commented 9 years ago

I have the same problem. Will see what we can do. I'll keep you informed.

idoo commented 9 years ago

:+1:

alejandromagnorsky commented 9 years ago

+1