Vaadin-grid: Grid "recalculateColumnWidths" method automatically scrolls the grid horizontally to the starting position.

Created on 5 Oct 2020  路  6Comments  路  Source: vaadin/vaadin-grid

Description

I've listened to scroll events and added my own logic with something like grid.$.table.addEventListener('scroll', grid.recalculateColumnWidths()).

This causes the grid columns with auto-width to update.

Now, when I scroll the grid vertically, the code works as expected without any issues.

While scrolling the grid horizontally (I have a large table so have a horizontal scrollbar on the grid), the following happens:

Expected outcome

I wish the grid to scroll horizontally to my desired location and stay fixed.

image

Actual outcome

The grid scrolls back to the starting position and doesn't stick to the location where I scrolled the grid.

image

In the above image, the grid has scrolled automatically to this starting position from my desired location.

Browsers Affected

  • [x] Chrome
  • [x] Firefox

@tomivirkki @web-padawan

Low Minor bug

Most helpful comment

Confirmed, can be reproduced using the demo. https://cdn.vaadin.com/vaadin-grid/5.6.10/demo/#grid-columns-demos

All 6 comments

Confirmed, can be reproduced using the demo. https://cdn.vaadin.com/vaadin-grid/5.6.10/demo/#grid-columns-demos

Workaround:

grid.$.table.addEventListener('scroll', () => {
  const scrollLeft = grid.$.table.scrollLeft;
  grid.recalculateColumnWidths()
  grid.$.table.scrollLeft = scrollLeft;
});

I recommend using some kind of throttling for this however, as running recalculateColumnWidths on every single scroll event would negatively affect scrolling performance.

Workaround:

grid.$.table.addEventListener('scroll', () => {
  const scrollLeft = grid.$.table.scrollLeft;
  grid.recalculateColumnWidths()
  grid.$.table.scrollLeft = scrollLeft;
});

I recommend using some kind of throttling for this however, as running recalculateColumnWidths on every single scroll event would negatively affect scrolling performance.

@tomivirkki I'm afraid it won't work. Because what happens is:

  • Let's say I scroll to a horizontal position to 480px.
  • The scroll event fires
  • We hold the value of scrollLeft = 480
  • grid.recalculateColumnWidths() will work as intended and will scroll back the grid to its horizontal starting point i.e. 0
  • We set grid.$.table.scrollLeft = 480

Now, this is where the problem begins:

  • As the grid.recalculateColumnWidths() is buggy, when it gets executed, it scrolls the grid from 480 to 0 itself, what this does is, triggers the scroll event again.

Now,

  • The scroll event fires
  • We hold the value of scrollLeft = 0
  • grid.recalculateColumnWidths() will work as intended and will scroll back the grid to its horizontal starting point i.e. 0
  • We set grid.$.table.scrollLeft = 0

This way, the problem still remains.

Maybe you can set a flag to disable the listener logic while recalculate is being run:

  • horizontal position to 480px;
  • scroll event fires
  • enable the the flag myFlag = true;
  • We hold the value of scrollLeft = 480
  • grid.recalculateColumnWidths()

    • it fires a scroll event but the listener logic is not run again because it checks for the flag

  • We set grid.$.table.scrollLeft = 480
  • disable the flag myFlag = false;

@tomivirkki
:stop_sign: Ooooops! It didn't work! :cry:

Because, I'm using LitElement and as far as I understand, LitElement performs batch rendering to the updated props.
So, in that case,

First batch rendered animation frame:

  • horizontal position to 480px;
  • scroll event fires
  • enable the the flag myFlag = true;
  • We hold the value of scrollLeft = 480
  • grid.recalculateColumnWidths()

    • it fires a scroll event, but the scroll event happens in the next animation frame(event loop), not in this loop

  • We set grid.$.table.scrollLeft = 480
  • disable the flag myFlag = false;

Second batch animation frame:

  • The queued scroll event from the First batch section fires.
  • Sees the flag myFlag = false, so our flag logic here won't work as the subsequent chunk of code fires again.

Ah, I think what's going on. We're probably using different grid versions. With the newest version, the original workaround works just fine. See it running live at https://productive-neat-manuscript.glitch.me/ (source: https://glitch.com/edit/#!/productive-neat-manuscript)

Was this page helpful?
0 / 5 - 0 ratings