diff --git a/src/virtual-repeat.js b/src/virtual-repeat.js index a6fd9ae..7f41512 100644 --- a/src/virtual-repeat.js +++ b/src/virtual-repeat.js @@ -143,6 +143,9 @@ export class VirtualRepeat extends AbstractRepeater { } this._unsubscribeCollection(); clearInterval(this.calcDistanceToTopInterval); + if (this._sizeInterval) { + clearInterval(this._sizeInterval); + } } itemsChanged(): void { @@ -402,7 +405,7 @@ export class VirtualRepeat extends AbstractRepeater { return this.view(0) ? this.view(0).overrideContext.$index : -1; } - _calcInitialHeights(itemsLength: number) { + _calcInitialHeights(itemsLength: number): void { if (this._viewsLength > 0 && this._itemsLength === itemsLength || itemsLength <= 0) { return; } @@ -411,7 +414,14 @@ export class VirtualRepeat extends AbstractRepeater { let firstViewElement = this.view(0).lastChild; this.itemHeight = calcOuterHeight(firstViewElement); if (this.itemHeight <= 0) { - throw new Error('Could not calculate item height'); + this._sizeInterval = setInterval(()=>{ + let newCalcSize = calcOuterHeight(firstViewElement); + if (newCalcSize > 0) { + clearInterval(this._sizeInterval); + this.itemsChanged(); + } + }, 500); + return; } this.scrollContainerHeight = this._fixedHeightContainer ? this._calcScrollHeight(this.scrollContainer) : document.documentElement.clientHeight; this.elementsInView = Math.ceil(this.scrollContainerHeight / this.itemHeight) + 1; @@ -426,6 +436,7 @@ export class VirtualRepeat extends AbstractRepeater { // TODO This will cause scrolling back to top when swapping collection instances that have different lengths - instead should keep the scroll position this.scrollContainer.scrollTop = 0; this._first = 0; + return; } _calcScrollHeight(element: Element): number { diff --git a/test/virtual-repeat-integration.spec.js b/test/virtual-repeat-integration.spec.js index 4c6e5cf..d2909ed 100644 --- a/test/virtual-repeat-integration.spec.js +++ b/test/virtual-repeat-integration.spec.js @@ -183,6 +183,11 @@ describe('VirtualRepeat Integration', () => { let create; let items; + let hiddenComponent; + let hiddenCreate; + let hiddenVirtualRepeat; + let hiddenViewModel; + beforeEach(() => { items = []; for(let i = 0; i < 1000; ++i) { @@ -197,10 +202,23 @@ describe('VirtualRepeat Integration', () => { virtualRepeat = component.sut; viewModel = component.viewModel; }); + + hiddenComponent = StageComponent + .withResources('src/virtual-repeat') + .inView(`
`) + .boundTo({ items: items }); + + hiddenCreate = hiddenComponent.create().then(() => { + hiddenVirtualRepeat = hiddenComponent.sut; + hiddenViewModel = hiddenComponent.viewModel; + }); }); afterEach(() => { component.cleanUp(); + hiddenComponent.cleanUp(); }); describe('handles delete', () => { @@ -296,6 +314,18 @@ describe('VirtualRepeat Integration', () => { it('handles splice', done => { create.then(() => validateSplice(virtualRepeat, viewModel, done)); }); + + it('handles displaying when initially hidden', done => { + hiddenCreate.then(() => { + hiddenVirtualRepeat.scrollContainer.style.display = "block"; + window.requestAnimationFrame(()=>{ + window.setTimeout(()=>{ + validateState(hiddenVirtualRepeat, hiddenViewModel); + done(); + }, 750) + }); + }); + }); }); describe('iterating table', () => {