From 288df86477167912da3c6f2b5464c534d6ca3126 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Nov 2016 18:22:23 -0600 Subject: [PATCH] fix(virtual-scroll): redraw empty list when updated with no records Closes #6512 --- .../virtual-scroll/test/list/app-module.ts | 62 +++++++++++++++++++ .../virtual-scroll/test/list/main.html | 37 +++++++++++ .../test/virtual-scroll.spec.ts | 25 +++++++- .../virtual-scroll/virtual-scroll.ts | 4 +- src/components/virtual-scroll/virtual-util.ts | 18 ++++-- 5 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/components/virtual-scroll/test/list/app-module.ts create mode 100644 src/components/virtual-scroll/test/list/main.html diff --git a/src/components/virtual-scroll/test/list/app-module.ts b/src/components/virtual-scroll/test/list/app-module.ts new file mode 100644 index 00000000000..aaa37f89e9b --- /dev/null +++ b/src/components/virtual-scroll/test/list/app-module.ts @@ -0,0 +1,62 @@ +import { Component, NgModule } from '@angular/core'; +import { IonicApp, IonicModule } from '../../../..'; + + +@Component({ + templateUrl: 'main.html' +}) +export class E2EPage { + items: Array<{title: string, date: string}>; + + constructor() { + this.emptyList(); + } + + fillList() { + this.items = []; + for (let i = 0; i < 59; i++) { + this.items.push({ + title: 'Item ' + i, + date: '23:' + (59 - i) + }); + } + } + + emptyList() { + this.items = []; + } + + itemTapped(ev: any, item: {title: string, date: string}) { + console.log(`itemTapped: ${item.title}`); + } + + reload() { + window.location.reload(true); + } + +} + + +@Component({ + template: '' +}) +export class E2EApp { + root = E2EPage; +} + + +@NgModule({ + declarations: [ + E2EApp, + E2EPage + ], + imports: [ + IonicModule.forRoot(E2EApp) + ], + bootstrap: [IonicApp], + entryComponents: [ + E2EApp, + E2EPage + ] +}) +export class AppModule {} diff --git a/src/components/virtual-scroll/test/list/main.html b/src/components/virtual-scroll/test/list/main.html new file mode 100644 index 00000000000..8a3c36e5e95 --- /dev/null +++ b/src/components/virtual-scroll/test/list/main.html @@ -0,0 +1,37 @@ + + + Virtual Scroll: List + + + + + + + + + +
+ + +
+ + + + + + + + {{item.title}} + + + {{item.date}} + + + + + + + +
diff --git a/src/components/virtual-scroll/test/virtual-scroll.spec.ts b/src/components/virtual-scroll/test/virtual-scroll.spec.ts index eadfb8010d5..3ef0c6e0f4d 100644 --- a/src/components/virtual-scroll/test/virtual-scroll.spec.ts +++ b/src/components/virtual-scroll/test/virtual-scroll.spec.ts @@ -1,5 +1,5 @@ import { VirtualCell, VirtualData, VirtualNode } from '../virtual-util'; -import { processRecords, populateNodeData, initReadNodes, getVirtualHeight, adjustRendered } from '../virtual-util'; +import { processRecords, populateNodeData, initReadNodes, getVirtualHeight, adjustRendered, estimateHeight } from '../virtual-util'; describe('VirtualScroll', () => { @@ -32,6 +32,15 @@ describe('VirtualScroll', () => { }; }); + describe('estimateHeight', () => { + + it('should return zero when no records', () => { + const h = estimateHeight(0, undefined, 100, .25); + expect(h).toEqual(0); + }); + + }); + describe('processRecords', () => { it('should load data for 100% width items', () => { @@ -212,6 +221,20 @@ describe('VirtualScroll', () => { describe('populateNodeData', () => { + it('should set no nodes when no records', () => { + nodes = []; + records = []; + + let startCellIndex = 0; + let endCellIndex = 0; + + populateNodeData(startCellIndex, endCellIndex, data.viewWidth, true, + cells, records, nodes, viewContainer, + itmTmp, hdrTmp, ftrTmp, false); + + expect(nodes.length).toBe(0); + }); + it('should skip already rendered, and create nodes', () => { cells = [ {row: 0, tmpl: TEMPLATE_ITEM}, diff --git a/src/components/virtual-scroll/virtual-scroll.ts b/src/components/virtual-scroll/virtual-scroll.ts index 034f228bb7e..dbadc82f414 100644 --- a/src/components/virtual-scroll/virtual-scroll.ts +++ b/src/components/virtual-scroll/virtual-scroll.ts @@ -363,9 +363,9 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy { * DOM READ THEN DOM WRITE */ update(checkChanges: boolean) { - var self = this; + const self = this; - if (!self._records || !self._records.length) return; + if (!self._records) return; if (checkChanges) { if (isPresent(self._differ)) { diff --git a/src/components/virtual-scroll/virtual-util.ts b/src/components/virtual-scroll/virtual-util.ts index aabfee27e2c..a4cea507b05 100644 --- a/src/components/virtual-scroll/virtual-util.ts +++ b/src/components/virtual-scroll/virtual-util.ts @@ -131,6 +131,13 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, v cells: VirtualCell[], records: any[], nodes: VirtualNode[], viewContainer: ViewContainerRef, itmTmp: TemplateRef, hdrTmp: TemplateRef, ftrTmp: TemplateRef, initialLoad: boolean): boolean { + + if (!records.length) { + nodes.length = 0; + // made changes + return true; + } + let madeChanges = false; let node: VirtualNode; let availableNode: VirtualNode; @@ -140,7 +147,6 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, v let viewInsertIndex: number = null; let totalNodes = nodes.length; let templateRef: TemplateRef; - startCellIndex = Math.max(startCellIndex, 0); endCellIndex = Math.min(endCellIndex, cells.length - 1); @@ -527,10 +533,14 @@ export function getVirtualHeight(totalRecords: number, lastCell: VirtualCell): n * NO DOM */ export function estimateHeight(totalRecords: number, lastCell: VirtualCell, existingHeight: number, difference: number): number { - let newHeight = getVirtualHeight(totalRecords, lastCell); + if (!totalRecords) { + return 0; + } + + const newHeight = getVirtualHeight(totalRecords, lastCell); - let percentToBottom = (lastCell.record / (totalRecords - 1)); - let diff = Math.abs(existingHeight - newHeight); + const percentToBottom = (lastCell.record / (totalRecords - 1)); + const diff = Math.abs(existingHeight - newHeight); if ((diff > (newHeight * difference)) || (percentToBottom > .995)) {