PrimeNG 使用异步管道延迟加载数据
PrimeNG Lazy load data with async pipe
我需要在 PrimeNG 数据中显示大量数据(400.000 条记录)table。为此,我需要延迟加载 table,因为您无法一次将所有数据加载到 table(这会使您的浏览器崩溃)。
为了创建 table 我使用了以下技术:
- Angular
7.2.4
- Angular/cdk
7.3.1
- ngrx-data
6.1.0-beta.3
(Ngrx http 请求包装器)
- PrimeNG
7.0.5
(UI框架)
- Rxjs
6.4.0
我想要什么
我正在尝试创建延迟加载 table,如 PrimeNG docs 所示,其中数据从服务器加载并显示在 table 中。当用户导航到下一个选项卡时,将加载并显示下一个 x 量的数据。
唯一的区别是我在将所有数据提供给 table 组件之前从服务器获取所有数据。这样我只需要从数据源中选择某些数据并将其显示给用户。
问题
在尝试实现它时,我 运行 遇到了 (onLazyLoad)
函数仅调用一次的问题,在 onInit()
阶段,在从服务器加载数据之前。
我可以通过添加 [lazyLoadOnInit]="false"
来撤消此操作,但这会导致延迟加载函数根本不会被调用。我希望我可以通过在加载数据时更改 [totalRecords]
属性 来触发加载功能,但这也不会触发该功能。
我在 PrimeNG p-table code 中找不到可用于触发 (onLazyLoad)
的任何其他函数,还是我遗漏了什么?
代码
public ngOnInit(): void {
this.cars$ = this.carService.entities$; // = []
this.carService.getAll(); // = [Car, Car, Car, Car] OR []
}
this.carService.entities$
的默认值为 []
并填充了 getAll()
函数的结果(如果没有结果,也可以是 []
)
我在 a StackBlitz 中重现了我的问题。在这里您可以看到数据从未显示,因为 (onLazyLoad)
仅在第一次调用时被调用,当时数据为空。
请注意,我使用 Angular Async pipe 将数据传递到我的组件中。这意味着我需要检查 ngOnChanges()
函数中的更改。
像这样更新 app.template
<ng-container *ngIf="cars$ | async as data">
<table-component [data]="data"></table-component>
</ng-container>
似乎 p-table lasyload 不会在数据更改时触发,即使数据 属性 从 undefined
更改为 object(arry)
已更新
没有异步管道
获取数据
public ngOnInit(): void {
this.carService.getAll().subscribe(data => this.data = data);
}
ngOnChanges 方法
public ngOnChanges(change: SimpleChanges): void {
if(change.data) {
if (change.data.currentValue) {
this.datasource = change.data.currentValue;
this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;
this.cars = this.datasource.slice(0, 10); // row number
this.loading = false;
}
}
}
check this article explains how to use async pipe and change detection
感谢 malbarmawi 我设法用新记录更新了 table。唯一仍然存在的问题是延迟加载只触发了 table 的 onInit()
。这为时过早,因为数据尚未加载。
所以我需要找到一种触发延迟加载的方法。我注意到 table 的方法是 public,所以我可以将 table 作为 @ViewChild
注入并自己触发延迟加载。
/**
* A reference to the primeng table. Since all of it's methods are public we can
* directly access the methods we need to trigger lazy loading correctly.
*/
@ViewChild(Table)
private tableRef: Table;
public ngOnChanges(change: SimpleChanges): void {
if(change.data && change.data.currentValue) {
this.datasource = change.data.currentValue;
this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;
// Trigger lazy loading
this.tableRef.onPageChange({ first: 0, rows: this.rows });
}
}
因为我现在有延迟加载,所以我还可以实现一个虚拟滚动条来提高 table 的性能,并且可以处理我的 400.000 条记录。
为此,我只需要将 tables 属性更新为(注意虚拟属性):
<p-table [columns]="cols" [value]="cars" [scrollable]="true" [rows]="rows" [scrollHeight]="scrollHeight" [virtualRowHeight]="rowHeight" [virtualScroll]="true" [lazy]="true" (onLazyLoad)="loadCarsLazy($event)" [totalRecords]="totalRecords" [loading]="isLoading"></p-table>
可以找到此代码的完整示例 on stackblitz
我需要在 PrimeNG 数据中显示大量数据(400.000 条记录)table。为此,我需要延迟加载 table,因为您无法一次将所有数据加载到 table(这会使您的浏览器崩溃)。
为了创建 table 我使用了以下技术:
- Angular
7.2.4
- Angular/cdk
7.3.1
- ngrx-data
6.1.0-beta.3
(Ngrx http 请求包装器) - PrimeNG
7.0.5
(UI框架) - Rxjs
6.4.0
我想要什么
我正在尝试创建延迟加载 table,如 PrimeNG docs 所示,其中数据从服务器加载并显示在 table 中。当用户导航到下一个选项卡时,将加载并显示下一个 x 量的数据。
唯一的区别是我在将所有数据提供给 table 组件之前从服务器获取所有数据。这样我只需要从数据源中选择某些数据并将其显示给用户。
问题
在尝试实现它时,我 运行 遇到了 (onLazyLoad)
函数仅调用一次的问题,在 onInit()
阶段,在从服务器加载数据之前。
我可以通过添加 [lazyLoadOnInit]="false"
来撤消此操作,但这会导致延迟加载函数根本不会被调用。我希望我可以通过在加载数据时更改 [totalRecords]
属性 来触发加载功能,但这也不会触发该功能。
我在 PrimeNG p-table code 中找不到可用于触发 (onLazyLoad)
的任何其他函数,还是我遗漏了什么?
代码
public ngOnInit(): void {
this.cars$ = this.carService.entities$; // = []
this.carService.getAll(); // = [Car, Car, Car, Car] OR []
}
this.carService.entities$
的默认值为 []
并填充了 getAll()
函数的结果(如果没有结果,也可以是 []
)
我在 a StackBlitz 中重现了我的问题。在这里您可以看到数据从未显示,因为 (onLazyLoad)
仅在第一次调用时被调用,当时数据为空。
请注意,我使用 Angular Async pipe 将数据传递到我的组件中。这意味着我需要检查 ngOnChanges()
函数中的更改。
像这样更新 app.template
<ng-container *ngIf="cars$ | async as data">
<table-component [data]="data"></table-component>
</ng-container>
似乎 p-table lasyload 不会在数据更改时触发,即使数据 属性 从 undefined
更改为 object(arry)
已更新
没有异步管道 获取数据
public ngOnInit(): void {
this.carService.getAll().subscribe(data => this.data = data);
}
ngOnChanges 方法
public ngOnChanges(change: SimpleChanges): void {
if(change.data) {
if (change.data.currentValue) {
this.datasource = change.data.currentValue;
this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;
this.cars = this.datasource.slice(0, 10); // row number
this.loading = false;
}
}
}
check this article explains how to use async pipe and change detection
感谢 malbarmawi 我设法用新记录更新了 table。唯一仍然存在的问题是延迟加载只触发了 table 的 onInit()
。这为时过早,因为数据尚未加载。
所以我需要找到一种触发延迟加载的方法。我注意到 table 的方法是 public,所以我可以将 table 作为 @ViewChild
注入并自己触发延迟加载。
/**
* A reference to the primeng table. Since all of it's methods are public we can
* directly access the methods we need to trigger lazy loading correctly.
*/
@ViewChild(Table)
private tableRef: Table;
public ngOnChanges(change: SimpleChanges): void {
if(change.data && change.data.currentValue) {
this.datasource = change.data.currentValue;
this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;
// Trigger lazy loading
this.tableRef.onPageChange({ first: 0, rows: this.rows });
}
}
因为我现在有延迟加载,所以我还可以实现一个虚拟滚动条来提高 table 的性能,并且可以处理我的 400.000 条记录。
为此,我只需要将 tables 属性更新为(注意虚拟属性):
<p-table [columns]="cols" [value]="cars" [scrollable]="true" [rows]="rows" [scrollHeight]="scrollHeight" [virtualRowHeight]="rowHeight" [virtualScroll]="true" [lazy]="true" (onLazyLoad)="loadCarsLazy($event)" [totalRecords]="totalRecords" [loading]="isLoading"></p-table>
可以找到此代码的完整示例 on stackblitz