我目前正在使用 Angular 12 开发一个包含 PrimeNG 12 表的项目,但我在 Angular 的更改检测和表更新方面遇到了一些麻烦,特别是试图阻止 PrimeNG
p-table
滚动回顶部关于数据刷新。
对于一些背景,我有一个服务(我们称之为
LocationService
),负责保存位置列表并每隔 500 毫秒更新一次。类似于以下内容:
位置.ts
interface Location {
id: string;
lat: number;
lng: number
}
位置.service.ts
// RxJS Behaviour Subjects
_locationUpdates$: BehaviorSubject<Location[]> = new BehaviorSubject<Location[]>([]);
// RxJS Observables
locationUpdates$: Observable<Location[]> = _locationUpdates.asObservable();
// Service Function
startUpdates() {
// Called within a service
timer(0, 500).subscribe(() => {
this._locations.forEach(location => {
location.lat = // ... some method to calculate new latitude
location.lng = // ... some method to calculate new longitude
});
this._locationUpdates$.next(this._locations);
});
}
现在,我有了一个订阅位置更新并将其显示为
(Lat, Lng)
中的 p-table
的组件,但也要求经度在 -45.0 到 45.0 度之间(其他组件可能没有这个要求)要求)。滚动顺序并不重要,尽管大多数时候它的顺序相同,因为行变化不大。
我目前正在像这样订阅它,使用虚拟滚动,因为可能有数百行:
位置组件.html
<ng-container *ngIf="locations$ | async as locations">
<p-table
dataKey="id"
scrollHeight="flex"
[rows]="100"
[scrollable]="true"
[value]="locations"
[virtualScroll]="true"
[virtualRowHeight]="34"
>
<ng-template pTemplate="header">
<tr>
<th>Latitude</th>
<th>Longitude</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-location>
<tr>
<td>{{ location.lat }}</td>
<td>{{ location.lng }}</td>
</tr>
</ng-template>
</p-table>
</ng-container>
位置组件.ts
// RxJS observables
locations$: Observable<Location[]>;
// Constructor
constructor(private _locationService: LocationService) {
locations$ = _locationService.locationUpdates$
.pipe(
map(locations => locations.filter(location => location.lng >= -45.0 && location.lng <= 45.0))
)
}
这里的问题是,当我运行代码时,每次刷新数据时表格都会对齐到顶部。我认为这是由于数组引用发生变化造成的。但是,如果我离开
async
管道并使用本地数组,只需在更新时对其进行修改,如下所示:
.subscribe(locations => {
this._locations.splice(0, this._locations.length, ...locations.filter(location => location.lng >= -45.0 && location.lng <= 45.0));
this._changeDetectorRef.detectChanges();
}
Angular 没有检测到变化,即使他
detectChanges()
调用(它似乎什么也没做)。使用像 this._locations = this._locations.slice()
这样的东西以另一种方式通知它只会让我回到上面的问题。
我向你们提出的问题是这样的:有人对我如何解决这个问题有任何建议吗?我的目标是每 X 毫秒刷新一次数据,但也允许用户在更新时滚动。
任何帮助将不胜感激!
好吧,所以我设法找到了这背后的罪魁祸首 - PrimeNG 的默认表行为是每次应用新过滤器时调用函数
resetScrollTop()
。
就我而言,我在表中添加了许多过滤器(文本过滤器、几个布尔过滤器等),这意味着每次表数据每 500 毫秒左右更新一次,这些过滤器都会重新应用,导致表格滚动位置不断重置(如此处的 PrimeNG 源代码所示)。
我设法通过简单地覆盖这个特定表的函数来以一种有点古怪的方式解决这个问题:
位置组件.html
<p-table #locationsTable ...> ... </p-table>
位置组件.ts
ngAfterViewInit() {
if (this.locationsTable != null) {
this.locationsTable.resetScrollTop = function() { }
}
}
这似乎暂时解决了这个问题,尽管如果有人知道更好的方法,我总是愿意听到它。希望这个答案能够帮助将来遇到类似情况的其他人。
还有其他合理的答案吗? 这不是一个正确的修复方法:(