mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(virtual-scroll): redraw empty list when updated with no records
Closes #6512
This commit is contained in:
62
src/components/virtual-scroll/test/list/app-module.ts
Normal file
62
src/components/virtual-scroll/test/list/app-module.ts
Normal file
@@ -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: '<ion-nav [root]="root"></ion-nav>'
|
||||
})
|
||||
export class E2EApp {
|
||||
root = E2EPage;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
E2EApp,
|
||||
E2EPage
|
||||
],
|
||||
imports: [
|
||||
IonicModule.forRoot(E2EApp)
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
entryComponents: [
|
||||
E2EApp,
|
||||
E2EPage
|
||||
]
|
||||
})
|
||||
export class AppModule {}
|
||||
37
src/components/virtual-scroll/test/list/main.html
Normal file
37
src/components/virtual-scroll/test/list/main.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>Virtual Scroll: List</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button (click)="reload()">
|
||||
Reload
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
|
||||
|
||||
<ion-content>
|
||||
|
||||
<div padding>
|
||||
<button ion-button (click)="fillList()">Fill List</button>
|
||||
<button ion-button (click)="emptyList()">Empty List</button>
|
||||
</div>
|
||||
|
||||
<ion-list [virtualScroll]="items">
|
||||
|
||||
<ion-item text-wrap *virtualItem="let item" (click)="itemTapped($event, item)">
|
||||
|
||||
<ion-row class="item-row">
|
||||
<ion-col class="item-title" width-80>
|
||||
{{item.title}}
|
||||
</ion-col>
|
||||
<ion-col class="item-time" width-20>
|
||||
{{item.date}}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
|
||||
</ion-content>
|
||||
@@ -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},
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -131,6 +131,13 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, v
|
||||
cells: VirtualCell[], records: any[], nodes: VirtualNode[], viewContainer: ViewContainerRef,
|
||||
itmTmp: TemplateRef<Object>, hdrTmp: TemplateRef<Object>, ftrTmp: TemplateRef<Object>,
|
||||
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<any>;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
let percentToBottom = (lastCell.record / (totalRecords - 1));
|
||||
let diff = Math.abs(existingHeight - newHeight);
|
||||
const newHeight = getVirtualHeight(totalRecords, lastCell);
|
||||
|
||||
const percentToBottom = (lastCell.record / (totalRecords - 1));
|
||||
const diff = Math.abs(existingHeight - newHeight);
|
||||
|
||||
if ((diff > (newHeight * difference)) ||
|
||||
(percentToBottom > .995)) {
|
||||
|
||||
Reference in New Issue
Block a user