angular-ui / ui-scroll

Unlimited bidirectional scrolling over a limited element buffer for AngularJS applications
http://angular-ui.github.io/ui-scroll/demo/
MIT License
327 stars 107 forks source link

Grid display element height #213

Open conraddamon opened 6 years ago

conraddamon commented 6 years ago

I just ran into an interesting issue with grid layout. When effectiveHeight() is called in order to determine whether more data needs to be loaded, it calculates the bottom position by adding up the heights of each element. Unfortunately, that happens before Angular has rendered the item, and the pre-render height can differ from the rendered height if a table with sized columns is being used.

For example, let's say the rendered item is just a letter, so the column width is something like 12px. If the Angular code is something like {{pickSomeRandomLetter()}}, it will blow out the table cell vertically in its pre-render form, and outerHeight() will return something way too large, throwing all the calculations off. What I ended up seeing is that data stopped loading early, so the table didn't even fill the container.

The right way to fix this would be to have the height measurement done after Angular has rendered the items, but I have no idea if that's even possible. Any other solution is likely to be pretty hacky.

Any ideas?

dhilt commented 6 years ago

@conraddamon I tried to play with grid-layout demos to catch the moment when effectiveHeight() might be called while the items were not compiled. And I have never seen the following condition satisfied within the effectiveHeight method:

elements.some(item => item.element[0].innerHTML.indexOf('{') > 0)

It means that each element's template had been compiled prior to the moment when the effectiveHeight method was called. Also I tried big template trick... I didn't see any gaps.

Maybe I'm doing something wrong, could you help me to reproduce the issue and provide more detailed steps?

conraddamon commented 6 years ago

It turns out that the fix was pretty trivial: use ng-bind rather than directly including the Angular template code. For example, change

<td ui-scroll-td><div>{{logline.timestamp | date:'MMM d'}}</div></td>

to

<td ui-scroll-td><div ng-bind="logline.timestamp | date:'MMM d'}"></div></td>

I was able to repro the issue by undoing that change. This time I didn't see it on initial load, but I did see it when scrolling up to force a data load and another call to effectiveHeight(). There's a screenshot here.