diff --git a/packages/component-base/src/virtualizer-iron-list-adapter.js b/packages/component-base/src/virtualizer-iron-list-adapter.js index e05365cce0..168c8bf73c 100644 --- a/packages/component-base/src/virtualizer-iron-list-adapter.js +++ b/packages/component-base/src/virtualizer-iron-list-adapter.js @@ -551,9 +551,19 @@ export class IronListAdapter { this._adjustVirtualIndexOffset(this._scrollTop - (this.__previousScrollTop || 0)); const delta = this.scrollTarget.scrollTop - this._scrollPosition; + const lastIndexVisible = this.adjustedLastVisibleIndex === this.size - 1; + const hasEmptySpace = lastIndexVisible && this._physicalBottom < this._scrollBottom; + super._scrollHandler(); - if (this._physicalCount !== 0) { + const needToCreateItemsAbove = lastIndexVisible && (delta < 0 || hasEmptySpace); + if (needToCreateItemsAbove) { + const idxAdjustment = Math.round((delta - this._scrollOffset) / this._physicalAverage); + this._virtualStart = Math.max(0, this._virtualStart + idxAdjustment); + this._physicalStart = Math.max(0, this._physicalStart + idxAdjustment); + this._physicalTop = Math.min(Math.floor(this._virtualStart) * this._physicalAverage, this._scrollPosition); + this._update(); + } else if (this._physicalCount !== 0) { const isScrollingDown = delta >= 0; const reusables = this._getReusables(!isScrollingDown); diff --git a/packages/component-base/test/virtualizer-scrolling.test.js b/packages/component-base/test/virtualizer-scrolling.test.js index 92624853c3..27f3beb7c0 100644 --- a/packages/component-base/test/virtualizer-scrolling.test.js +++ b/packages/component-base/test/virtualizer-scrolling.test.js @@ -231,9 +231,13 @@ describe('virtualizer - scrollbar scrolling', () => { // Sanity check for iron-list internal properties const adapter = virtualizer.__adapter; const firstItem = adapter._physicalItems[adapter._physicalStart]; - expect(firstItem.__virtualIndex).to.equal(adapter._virtualStart); + expect(firstItem.__virtualIndex).to.closeTo(adapter._virtualStart, 10); } + const adapter = virtualizer.__adapter; + const firstItem = adapter._physicalItems[adapter._physicalStart]; + expect(firstItem.__virtualIndex).to.eq(adapter._virtualStart); + // There should be an item at the bottom of the viewport await nextFrame(); const listRect = scrollTarget.getBoundingClientRect(); diff --git a/packages/grid/test/resizing.test.js b/packages/grid/test/resizing.test.js index 7c2a196941..457942295e 100644 --- a/packages/grid/test/resizing.test.js +++ b/packages/grid/test/resizing.test.js @@ -111,6 +111,36 @@ describe('resizing', () => { expect(grid.$.scroller.getBoundingClientRect().bottom).to.equal(grid.$.table.getBoundingClientRect().bottom); }); + it('should create rows when resized while scrolled to bottom', async () => { + // Have a full width grid inside a fixed width container + component = fixtureSync(` +