Skip to content

Commit 4efe380

Browse files
authored
Fix server side virtual scroll (swimlane#1853)
1 parent 96b30cf commit 4efe380

File tree

2 files changed

+64
-36
lines changed

2 files changed

+64
-36
lines changed

projects/swimlane/ngx-datatable/src/lib/components/body/body.component.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
ChangeDetectionStrategy
1212
} from '@angular/core';
1313
import { ScrollerComponent } from './scroller.component';
14-
import { MouseEvent } from '../../events';
1514
import { SelectionType } from '../../types/selection.type';
1615
import { columnsByPin, columnGroupWidths } from '../../utils/column';
1716
import { RowHeightCache } from '../../utils/row-height-cache';
@@ -57,10 +56,10 @@ import { translateXY } from '../../utils/translate';
5756
[rowDetail]="rowDetail"
5857
[groupHeader]="groupHeader"
5958
[offsetX]="offsetX"
60-
[detailRowHeight]="getDetailRowHeight(group[i], i)"
59+
[detailRowHeight]="getDetailRowHeight(group && group[i], i)"
6160
[row]="group"
6261
[expanded]="getRowExpanded(group)"
63-
[rowIndex]="getRowIndex(group[i])"
62+
[rowIndex]="getRowIndex(group && group[i])"
6463
(rowContextmenu)="rowContextmenu.emit($event)"
6564
>
6665
<datatable-body-row
@@ -76,7 +75,7 @@ import { translateXY } from '../../utils/translate';
7675
[expanded]="getRowExpanded(group)"
7776
[rowClass]="rowClass"
7877
[displayCheck]="displayCheck"
79-
[treeStatus]="group.treeStatus"
78+
[treeStatus]="group && group.treeStatus"
8079
(treeAction)="onTreeAction(group)"
8180
(activate)="selector.onActivate($event, indexes.first + i)"
8281
>
@@ -175,8 +174,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy {
175174

176175
@Input() set offset(val: number) {
177176
this._offset = val;
178-
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization))
179-
this.recalcLayout();
177+
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization)) this.recalcLayout();
180178
}
181179

182180
get offset(): number {
@@ -773,7 +771,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy {
773771
if (!expanded || !expanded.length) return -1;
774772

775773
const rowId = this.rowIdentity(row);
776-
return expanded.findIndex((r) => {
774+
return expanded.findIndex(r => {
777775
const id = this.rowIdentity(r);
778776
return id === rowId;
779777
});
Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import { Component } from '@angular/core';
22
import { MockServerResultsService } from './mock-server-results-service';
3-
import { PagedData } from './model/paged-data';
43
import { CorporateEmployee } from './model/corporate-employee';
54
import { Page } from './model/page';
65
import { ColumnMode } from 'projects/swimlane/ngx-datatable/src/public-api';
6+
import { delay } from 'rxjs/operators';
7+
8+
interface PageInfo {
9+
offset: number;
10+
pageSize: number;
11+
limit: number;
12+
count: number;
13+
}
714

815
@Component({
916
selector: 'virtual-paging-demo',
@@ -24,60 +31,83 @@ import { ColumnMode } from 'projects/swimlane/ngx-datatable/src/public-api';
2431
<ngx-datatable
2532
class="material"
2633
[rows]="rows"
27-
[columns]="[{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]"
34+
[columns]="[
35+
{ name: 'Name', sortable: false },
36+
{ name: 'Gender', sortable: false },
37+
{ name: 'Company', sortable: false }
38+
]"
2839
[columnMode]="ColumnMode.force"
2940
[headerHeight]="50"
41+
[loadingIndicator]="isLoading > 0"
3042
[scrollbarV]="true"
3143
[footerHeight]="50"
3244
[rowHeight]="50"
3345
[externalPaging]="true"
34-
[count]="page.totalElements"
35-
[offset]="page.pageNumber"
46+
[externalSorting]="true"
47+
[count]="totalElements"
48+
[offset]="pageNumber"
3649
(page)="setPage($event)"
3750
>
3851
</ngx-datatable>
3952
</div>
4053
`
4154
})
4255
export class VirtualPagingComponent {
43-
page = new Page();
44-
rows = new Array<CorporateEmployee>();
56+
totalElements: number;
57+
pageNumber: number;
58+
rows: CorporateEmployee[];
4559
cache: any = {};
4660

4761
ColumnMode = ColumnMode;
4862

63+
isLoading = 0;
64+
4965
constructor(private serverResultsService: MockServerResultsService) {
50-
this.page.pageNumber = 0;
66+
this.pageNumber = 0;
5167
}
5268

53-
/**
54-
* Populate the table with new data based on the page number
55-
* @param page The page to select
56-
*/
57-
setPage(pageInfo) {
58-
this.page.pageNumber = pageInfo.offset;
59-
this.page.size = pageInfo.pageSize;
69+
setPage(pageInfo: PageInfo) {
70+
// current page number is determined by last call to setPage
71+
this.pageNumber = pageInfo.offset;
72+
73+
// don't load same data twice
74+
if (this.cache[pageInfo.offset]) return;
75+
this.cache[pageInfo.offset] = true;
76+
77+
// counter of pages loading
78+
this.isLoading++;
79+
80+
// class to idendify loading page
81+
const page = new Page();
82+
page.pageNumber = pageInfo.offset;
83+
page.size = pageInfo.pageSize;
6084

61-
// cache results
62-
// if(this.cache[this.page.pageNumber]) return;
85+
this.serverResultsService
86+
.getResults(page)
87+
.pipe(delay(new Date(Date.now() + 1000 * Math.random()))) // simulating variability in returned data
88+
.subscribe(pagedData => {
89+
// update total count
90+
this.totalElements = pagedData.page.totalElements;
6391

64-
this.serverResultsService.getResults(this.page).subscribe(pagedData => {
65-
this.page = pagedData.page;
92+
// create array to store data if missing
93+
if (!this.rows) {
94+
// length should be total count
95+
this.rows = new Array<CorporateEmployee>(pagedData.page.totalElements || 0);
96+
}
6697

67-
// calc start
68-
const start = this.page.pageNumber * this.page.size;
98+
// calc starting index
99+
const start = pagedData.page.pageNumber * pagedData.page.size;
69100

70-
// copy rows
71-
const rows = [...this.rows];
101+
// copy existing data
102+
const rows = [...this.rows];
72103

73-
// insert rows into new position
74-
rows.splice(start, 0, ...pagedData.data);
104+
// insert new rows into new position
105+
rows.splice(start, pagedData.page.size, ...pagedData.data);
75106

76-
// set rows to our new rows
77-
this.rows = rows;
107+
// set rows to our new rows
108+
this.rows = rows;
78109

79-
// add flag for results
80-
this.cache[this.page.pageNumber] = true;
81-
});
110+
this.isLoading--;
111+
});
82112
}
83113
}

0 commit comments

Comments
 (0)