React-data-grid: Dynamic height adjustment

Created on 10 Feb 2016  Â·  19Comments  Â·  Source: adazzle/react-data-grid

First of all, thanks for this awesome component!

My request has to do with dynamic resizing of the grid's height.

So I'm placing a grid at the bottom of the page. Sometimes it contains a lot of rows, in which case I would like it to automatically expand vertically to the bottom of the page. If I make the browser shorter in height, the grid should also shrink accordingly to remain in sync with the page's height.

There are other times there are just a couple of rows, in which case I would prefer the grid to shrink its height to encapsulate just those rows. But then if I shrink my window and the grid's height no longer fits inside the page, it should dynamically shrink.

Is this possible today and if not, what would it take?

Thanks,
Alvaro

Most helpful comment

<ReactDataGrid minHeight={rows.length*35 + 50}> </ReactDataGrid>
With each row of height 35px and 50px extra space. Now minHeight will be adjusted based on the number of rows.

All 19 comments

something like this:

export let DataGrid = React.createClass({

getInitialState: function(){
return {rows: this.props.route.rows, height:
window.innerHeight-heightOffset};
},

handleResize: function(e) {
this.setState({height: window.innerHeight-heightOffset});
},

componentDidMount: function() {
window.addEventListener('resize', this.handleResize);
},

componentWillUnmount: function() {
window.removeEventListener('resize', this.handleResize);
},

render: function() {
return (
minHeight={this.state.height}
/>
);
}
});

On 10 February 2016 at 21:42, alvaro1728 [email protected] wrote:

First of all, thanks for this awesome component!

My request has to do with dynamic resizing of the grid's height.

So I'm placing a grid at the bottom of the page. Sometimes it contains a
lot of rows, in which case I would like it to automatically expand
vertically to the bottom of the page. If I make the browser shorter in
height, the grid should also shrink accordingly to remain in sync with the
page's height.

There are other times there are just a couple of rows, in which case I
would prefer the grid to shrink its height to encapsulate just those rows.
But then if I shrink my window and the grid's height no longer fits inside
the page, it should dynamically shrink.

Is this possible today and if not, what would it take?

Thanks,
Alvaro

—
Reply to this email directly or view it on GitHub
https://github.com/adazzle/react-data-grid/issues/207.

Andrew McGregor
07940 22 33 11

Nicely done Andrew, thanks! I'm new to React and this is a great example of how easy adding this functionality is. The only missing part is to shrink the grid's height based on the header + rows when the grid only has a couple of rows. Do you know if the grid has a property that gives us the height of the header + rows?

Thanks,
Alvaro

Also, upon further testing, I noticed an issue with how the grid's vertical scrollbar is redrawn as I resize the window: the scrollbar will only allow me to scroll to the next to last row. The very last row will be hidden until I refresh the browser.

Perhaps I should add a delay while the window is being resized to avoid so many redraws.

Thanks,
Alvaro

Height is this.state.rows.length + css.

On 10 February 2016 at 23:48, alvaro1728 [email protected] wrote:

Also, upon further testing, I noticed an issue with how the grid's
vertical scrollbar is redrawn as I resize the window: the scrollbar will
only allow me to scroll to the next to last row. The very last row will be
hidden until I refresh the browser.

Perhaps I should add a delay while the window is being resized to avoid so
many redraws.

Thanks,
Alvaro

—
Reply to this email directly or view it on GitHub
https://github.com/adazzle/react-data-grid/issues/207#issuecomment-182638930
.

Andrew McGregor
07940 22 33 11

@alvaro1728 - Any luck with overcoming the hidden row? Encountering the same thing on my end when dynamically adjusting height of grid.

There's a row beneath here somewhere :smile::
image

It looks like when dynamically re-adjusted, div.react-grid-Canvas is not accounting for the header (div.react-grid-HeaderRow), thus acquires the full height of grid and pushing the last row below the scroll by the height of the header.

However, if you then readjust the window horizontally it re-acquires the proper height.

@joshparolin I've been out the past 5 days so I haven't had a chance to look at this. I see that you discovered that manually adjusting the width fixes the grid's height. So what's the programmatic fix for this issue? Thanks.

Any update on this bug? I really need to have it resolved, otherwise I'll have to consider another component. Thanks.

An ugly solution that I am using currently : creating and dispatching a fake resize event in componentWillUpdate of the "father" component. And then, when an event/panel resize change the minHeight, I have to create a second update of the props/state that will change only the minWidth (in fact I am cloning the original component changing only the minWidth).
Hope that helps while waiting for a fix :)

Hi @rico642, thanks for your post. I actually spent hours last night digging deep into this issue and noticed that there are actually two problems:

  1. Changing the grid's minHeight (after a vertical resize) causes the last row to disappear from the grid and it's not until a horizontal resize that it comes back.
  2. If you've scrolled down several rows and resize the page (causing minHeight to change), the whole grid goes blank (all rows disappear) and it's not until you scroll inside the grid that the rows reappear.

So I discovered that this is caused by two problems: the viewportHeight is not always adjusted after minHeight is changed and componentWillReceiveProps resets the scrollTop and scrollLeft properties after minHeight is changed. So it causes havoc when the grid's scrollTop position gets set to 0 while the grid itself is not scrolled to the top.

I was able to solve it by capturing the scrollTop/scrollLeft values before updating the minHeight, and then manually triggering updateScroll afterward, like this:

  handleResize() {
    if (!this.resizeTimer) {
      this.resizeTimer = setTimeout(() => {
        // Hack -- we need to grab the current viewport state before it gets wiped out after the minHeight is changed below.  Then we'll use the saved state to update the viewport later.
        const {viewportHeight} = this.refs.grid.refs.base._DOMMetrics.metrics;
        const viewportState = viewportHeight.component.state;

        // Update the grid's minHeight
        this.setState({height: this.calculateHeight()});

        // Hack -- since changing the minHeight does not update the viewport, we need to do it manually to fix a bug that removes the last row after resizing vertically.
        const height = viewportHeight.computator();
        if (height) {
          viewportHeight.component.updateScroll(viewportState.scrollTop, viewportState.scrollLeft, height, viewportHeight.component.props.rowHeight, viewportHeight.component.props.rowsCount);
        }          
        this.resizeTimer = 0;
      }, 1000);
    }
  }

It's a total hack but it fixed the problems, allowing my grid's height to vary based on the browser's height.

Cheers,
Alvaro

Any word on an official fix yet? We've encountered both issues @alvaro1728 listed above as well.

Bumping this...

This seems to be fixed in the latest version.

Bump. Definitely not fixed in the latest version,

and the problem is that if I use

minHeight={that.state.rows.length*rowHeight+offset},

I can't make the grid scrollable anymore. It just expands the whole viewport until the bottom.

And in the other case, we have this known issue of not making the last row visible.

http://www.awesomescreenshot.com/image/1802359/8eaf415ac9a9415dc135a8ef4ec3c575

In the screenshot: scrolled until the very last bottom. Last row is 'Test 50'. It's only visible until 'Test 49'.

I tried the hacks described above. They don't work.

Maybe this can help, it worked for me

_ minHeight={rows.length*100 > 500 ? 500 : rows.length*70}
... />_

If the quantity of rows is high I set a fixed height for the grid, if not I calculate the grid height with the number of rows * a fixed row height.

Maybe you can use the row height to multiply.

If someone is still looking for some kind of solution:

My problem was not only to make table dynamic, but also adjust its height to size of the window. Because I have several elements above the table, I'm not using 100% of window's height. And I made custom header so it has its own height. _tableItems_ is array of rows

const heightOfRows = ( tableItems.length * ROW_HEIGHT ) + HEADER_HEIGHT;  
const maxTableHeight = window.innerHeight * PERCENT_OF_WINDOW_HEIGHT;  
const minHeight = heightOfRows > maxTableHeight ? maxTableHeight : heightOfRows;  

I have a problem. After changing minHeight of grid, it try to reset its state in componentWillReceiveProps with getGridState(). But this getGridState method calculates visible row count and multiply it with 4. It cause to render 80 item instead of 20 in my case. And it slow effect performance.

In the first mount, updateScroll call fix unnecessarily high visible count to normal levels. (VisibleCount + 5 for example). It triggered by updateMetrics() and it called after getInitialState/getGridState.

Should componentWillReceiveProps call updateScroll or metricsUpdated after this.setState(this.getGridState(...)) (ViewportScrollMixin.js Line: 175). Like in #1030

I couldn't find any proper way to prevent table to stop rendering 4x items after I change minHeight.

<ReactDataGrid minHeight={rows.length*35 + 50}> </ReactDataGrid>
With each row of height 35px and 50px extra space. Now minHeight will be adjusted based on the number of rows.

Was this page helpful?
0 / 5 - 0 ratings