Search code examples
vaadinvaadin7

Vaadin Grid recalculateColumnWidths problems - how to make it more consistant


In my Vaadin 7 app, I call grid.recalculateColumnWidths(); after loading most grids. I do this because when I was refreshing one particular Grid, I noticed the column width was not changing. This fixed it with this one particular Grid, and probably a few others, but not with all grids. The documentation does not really explain a few things, and I was hoping someone could clarify some things so I can fix the problem:

  1. When is it triggered? In other words, in the cases where it does not work, could it be a timing issue? For Vaadin Flow, I see some people advising doing something like grid.getElement().executeJs("setTimeout(() => { this.recalculateColumnWidths() }, 0)");, so I guess this is a long-standing issue. Also, if you look at the low-level API, you will see that it clearly says that you cannot rely on proper columns widths after calling this function, as it is not done immediately. When I step into it in the debugger, it looks like it adds it to a queue of actions to complete later, so that seems to confirm things. How can I improve my chances of the resize being triggered?
  2. How does it handle columns where I explicitly set the width? If this is documented someplace (in API docs or in some posting someplace), I could not find it. When I stepped into the debugger, it was kind of hard to determine for sure.
  3. If I added a button to force a resizing, calling this recalculateColumnWidths() method, similar to what some users did in Vaadin 14 here, would it work? So let's say we initialize the width to one value (so we purposely truncate some columns, forcing them to make the column bigger), and we want to fully show all content in all columns when they click this button, is there a way to do that? Maybe clear all explicit column sizes and let normal resize logic work?

Solution

  • Let me preface this answer by saying that column width (re)calculation is a complex and relatively expensive task. It needs to be done at the right time - not too early and not too late. If it's done too early, subsequent changes to layouting will mean that size calculation will need to be done again. If it's done too late, it means that the UI will take longer to become responsive again. Trying to "play it safe" by doing column width recalculation more often than needed is an easy source of performance degradation - a Grid can have a LOT of columns, so the cost of recalculation compounds easily.

    1. There are many cases when column width recalculation is triggered. A couple of basic cases are during the layouting phase of the UI, or when a Grid is reattached, or when the inner width of the Grid changes (e.g. due to browser window resize), or when something is done to column sizes (e.g. min or max-width or expand ratio are set). Resizing is indeed queued as you can see here: https://github.com/vaadin/framework/blob/7.7/client/src/main/java/com/vaadin/client/widgets/Grid.java#L3280. It's definitely possible that there's a timing issue. Without the exact conditions of how a calculation goes wrong, it's hard to say when would be a good place to retry - there's no place where "everything is truly finally rendered so that you can schedule a little bit more rendering".
    2. The size of fixed-width columns will not need to be calculated, so these columns should be ignorable from this point of view. In fact, if you can set a fixed width to all or most columns, it will most likely mean a significant performance improvement.
    3. Yes, it could work.