【问题标题】:Is there a way to preserve PrimeNG table scroll position on data update?有没有办法在数据更新时保留 PrimeNG 表滚动位置?
【发布时间】:2021-09-17 12:41:28
【问题描述】:

我目前正在使用 Angular 12 处理 PrimeNG 12 表的项目,但我在 Angular 的更改检测和表更新方面遇到了一些问题,特别是试图阻止 PrimeNG p-table 滚动回数据刷新置顶。

在某些背景下,我有一个服务(我们称之为LocationService),它负责保存位置列表并每隔(例如,500 毫秒)更新一次。类似于以下内容:

location.ts

interface Location {
    id: string;
    lat: number;
    lng: number
}

location.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);
    });
}

现在,我有一个组件可以订阅位置更新并将它们显示为 p-table 中的 (Lat, Lng),但还要求经度在 -45.0 到 45.0 度之间(其他组件可能没有有这个要求)。滚动顺序无关紧要,尽管大多数情况下它的顺序相同,因为行并没有太大变化。

我目前正在订阅它,使用虚拟滚动,因为可能有数百个潜在的行:

location-component.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>

location-component.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 毫秒刷新一次数据,但也允许用户在更新时滚动。

任何帮助将不胜感激!

【问题讨论】:

    标签: javascript angular typescript datatable primeng


    【解决方案1】:

    好的,所以我设法找到了这背后的罪魁祸首——PrimeNG 的默认表格行为是在每次应用新过滤器时调用函数 resetScrollTop()

    在我的例子中,我在表格中添加了一些过滤器(文本过滤器、几个布尔过滤器等),这意味着每次表格数据每 500 毫秒左右更新一次,这些过滤器就会重新- 应用,导致表格滚动位置不断重置 (as seen in the PrimeNG source here)。

    我设法通过简单地覆盖这个特定表的函数来解决这个问题:

    location-component.html

    <p-table #locationsTable ...> ... </p-table>
    

    location-component.ts

    ngAfterViewInit() {
        if (this.locationsTable != null) {
            this.locationsTable.resetScrollTop = function() { }
        }
    }
    

    这似乎暂时解决了这个问题,尽管如果有人知道更好的方法,我总是愿意听到它。希望这个答案能帮助将来遇到类似情况的其他人。

    【讨论】:

      猜你喜欢
      • 2016-09-20
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      • 2021-07-31
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多