Skip to content

Commit c9df7d0

Browse files
fix: adjust virtualizer indexes when scrolling at the end (#9142) (#9516)
* fix: adjust virtualizer indexes when scrolling at the end * fix: do not get reusables when there are no physical items * fix: fix jumpy scrolling at virtualizer end * refactor: do not modify delta * refactor: revert changes in original path * refactor: move line back * test: add grid container resize test and modify an existing test * refactor: move the fix to resize handler and simplify index adjustment * refactor: update scroll top in order to have smooth scrolling Co-authored-by: Ugur Saglam <106508695+ugur-vaadin@users.noreply.github.com>
1 parent ec19662 commit c9df7d0

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

packages/component-base/src/virtualizer-iron-list-adapter.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,24 @@ export class IronListAdapter {
438438
}
439439
}
440440

441+
/** @override */
442+
_resizeHandler() {
443+
super._resizeHandler();
444+
445+
// Fixes an issue where the new items are not created on scroll target resize when the scroll position is around the end.
446+
// See https://github.com/vaadin/flow-components/issues/7307
447+
const lastIndexVisible = this.adjustedLastVisibleIndex === this.size - 1;
448+
const emptySpace = this._physicalTop - this._scrollPosition;
449+
if (lastIndexVisible && emptySpace > 0) {
450+
const idxAdjustment = Math.ceil(emptySpace / this._physicalAverage);
451+
this._virtualStart = Math.max(0, this._virtualStart - idxAdjustment);
452+
this._physicalStart = Math.max(0, this._physicalStart - idxAdjustment);
453+
// Scroll to end for smoother resize
454+
super.scrollToIndex(this._virtualCount - 1);
455+
this.scrollTarget.scrollTop = this.scrollTarget.scrollHeight - this.scrollTarget.clientHeight;
456+
}
457+
}
458+
441459
/**
442460
* Work around an iron-list issue with invalid item positioning.
443461
* See https://github.com/vaadin/flow-components/issues/4306

packages/grid/test/resizing.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,39 @@ describe('resizing', () => {
130130
expect(grid.$.scroller.getBoundingClientRect().bottom).to.equal(grid.$.table.getBoundingClientRect().bottom);
131131
});
132132

133+
it('should create rows when resized while scrolled to bottom', async () => {
134+
// Have a full width grid inside a fixed width container
135+
component = fixtureSync(`
136+
<div style="height: 200px;">
137+
<vaadin-grid style="height: 100%;">
138+
<vaadin-grid-column></vaadin-grid-column>
139+
</vaadin-grid>
140+
</div>
141+
`);
142+
grid = component.querySelector('vaadin-grid');
143+
grid.querySelector('vaadin-grid-column').renderer = (root, _, model) => {
144+
root.textContent = model.item.name;
145+
};
146+
const itemCount = 1000;
147+
grid.items = Array.from({ length: itemCount }, (_, i) => ({
148+
name: `Item ${i}`,
149+
}));
150+
// Scroll to end
151+
grid.scrollToIndex(itemCount - 1);
152+
await aTimeout(200);
153+
// Resize container
154+
for (let i = 0; i < 10; i++) {
155+
component.style.height = `${component.offsetHeight + 200}px`;
156+
flushGrid(grid);
157+
await aTimeout(50);
158+
}
159+
const gridRect = grid.getBoundingClientRect();
160+
// Get an element from the area where new rows should be created
161+
const elementInResizedArea = document.elementFromPoint(gridRect.left + 1, gridRect.top + 50);
162+
const isCell = elementInResizedArea && elementInResizedArea.tagName === 'VAADIN-GRID-CELL-CONTENT';
163+
expect(isCell).to.be.true;
164+
});
165+
133166
describe('flexbox parent', () => {
134167
beforeEach(() => {
135168
grid.style.height = grid.style.width = '';

0 commit comments

Comments
 (0)