分页只在第一页显示条目
Posted
技术标签:
【中文标题】分页只在第一页显示条目【英文标题】:pagination only showing entries on the first page 【发布时间】:2021-11-20 06:13:51 【问题描述】:由于包含超过 30k 条目的大量数据,我决定创建一个带有 paginaton 的 mat 表。所以它现在使用我的过滤器工作正常,我唯一的问题是只有第一页显示条目并且页面导航不起作用。所以如果我点击下一页,下一页是空的
这是我的分页器:
this.persons = data;
this.personsFiltered = new MatTableDataSource(this.persons);
this.personsFiltered.paginator = this.paginator;
FilterChanged() //this filter works with a input field to search for a special name
this.personsFiltered = of(this.persons).pipe(
//Name
map( p => (!this.vornameFilter || this.vornameFilter.trim() === '') ? p: p.filter((i: any) => i.vorname?.toLowerCase().includes(this.vornameFilter.toLowerCase()))),
map(p => p.slice(this.paginator?.pageIndex * this.paginator?.pageSize, this.paginator?.pageSize))
)
我的桌子:
<table mat-table [dataSource]="personsFiltered" *ngIf="personsFiltered">
<ng-container matColumnDef="Name">
<th mat-header-cell *matHeaderCellDef > Name </th>
<td mat-cell *matCellDef="let user">
user.nachname, user.vorname
</td>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator (click)="FilterChanged()" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
为什么不显示其他页面上的条目?
【问题讨论】:
【参考方案1】:-
您错过了
length
和pageSize
选项,请将它们提供给mat-paginator
,它应该会有所帮助:
<mat-paginator [length]="personsFiltered.data.length" [pageSize]="5" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
-
您还需要在过滤功能中修复分页 - 详情如下。
2a.
修复分页的第一种方法是从函数中删除这部分 (map(p => p.slice(this.paginator?.pageIndex * this.paginator?.pageSize, this.paginator?.pageSize))
) 并应用 MatTableDataSoruce
- 这是我绝对推荐的,因为它使事情变得更容易,如果你需要,它也可以更容易添加排序和将此排序与过滤相结合。 Angular Material 的文档(https://v5.material.angular.io/components/table/examples - 带分页的表格)中就是一个很好的例子,他们的 Stackblitz 例子在这里:https://stackblitz.com/angular/kbxroarjbeb
您还可以查看此处提供的示例:https://***.com/a/50269705/14556461
在这种方法中,分页由 mat-paginator
自动完成,您的自定义代码会删除应该在下一页显示的数据 - 分页器无法加载更多数据,因为该函数会删除数据。
2b.
另一种方法是更手动地进行分页 - 您可以使用来自mat-paginator
的page
事件,如下所示:
<mat-paginator
[length]="length"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
(page)="changePage($event)"
>
</mat-paginator>
然后在你的组件中:
changePage(pageEvent: PageEvent)
const startIndex = pageEvent.pageIndex * pageEvent.pageSize;
const endIndex = startIndex + pageEvent.pageSize;
this.personsFilteredForCurrentPage = this.personsFiltered.slice(startIndex, endIndex);
在 html 中,只需在 mat-table 中显示 personsFilteredForCurrentPage
而不是 personsFiltered
。更新过滤器时更新personsFiltered
。这样分页与过滤分离,因此您不必在每次切换页面时过滤所有项目。
当您更改表格中的过滤器时调用FilterChanged()
。
您还需要处理更改过滤器/过滤器时发生的情况 - 随着数据的更改,您还需要在过滤器更改后更新 personsFilteredForCurrentPage
以刷新表中的数据。
顺便说一句。这个(click)="FilterChanged()"
在这个地方看起来很奇怪——你确定它应该在这里吗?似乎应该在单击某些按钮或更改输入时调用此函数。无论如何,当您单击分页器时,我会避免调用它。
【讨论】:
感谢您的想法!长度选项让我的表格爆炸,所以我只使用 pageSize 和 PageSizeOptions :D 我还删除了过滤器中的地图线。现在因为我删除了它,它加载了我的所有数据,而不仅仅是 5 个元素。 我更新了我的答案,现在应该更清楚我的意思了,因为以前的版本不够清楚,可能会误导你。请检查我更新的答案,如果有帮助,请告诉我。 好的,所以尝试让 peopleFilteredForCurrentPage 成为 Observable ,就像你之前做的那样。这应该会触发表中的数据刷新,并使您的过滤恢复正常。或者使用自动处理数据刷新的DataSource(例如MatTableDataSource)(您只需像this.dataSource.data = newData
一样更新dataSource中的数据,并在表中刷新)
您是否尝试过使用更少的数据?您观察到的错误不应与数据量有关。是否可以在您观察此问题的地方使用您的代码创建 stackblitz?以这种方式帮助您会容易得多。
如果你愿意,你总是可以人为地在 stackblitz 上产生更多的数据(例如,准备生成这么多数据的函数)。不幸的是,如果不了解确切的代码,就无法提供帮助,但我希望您能够与您的朋友一起处理这个问题。如果没有 - 请尝试创建 stackblitz 并在那里人工生成数据。还要确保它确实是由数据量引起的(即尝试减少数据量以进行测试并检查一切是否正常)。更多数据只会让代码变慢,而不是损坏。【参考方案2】:
所以最后我们找到了解决方案。它比我们在这里想的要复杂得多。我们在后端控制器中创建了一个计数方法,如下所示:
[HttpGet("get/count")]
public int GetPersonensCount()
return _context.Personens.Count();
我们还将 count 方法处理到我的服务和订阅中,如下所示:
getPersonDetails(start: number = 0): Observable<PersonenSharing[]>
return this.http.get<PersonenSharing[]>(this.pController + start);
getData()
this.pService.getPersonCount().pipe(
tap(count =>
for(let i = 0; i < count; i+=100)
this.pService.getPersonDetails(i).subscribe(data =>
if(!this.persons)
this.persons = [];
this.personsFiltered = new MatTableDataSource(this.persons);
this.personsFiltered.paginator = this.paginator;
this.persons = this.persons.concat(data);
this.FilterChanged();
if(this.persons.length == count)
this.loaded = true;
)
)
).subscribe();
这就是它的工作原理,目前唯一的问题是性能。
【讨论】:
以上是关于分页只在第一页显示条目的主要内容,如果未能解决你的问题,请参考以下文章
使用 Angular JS 的自定义分页 - 需要在第一页显示 div 元素,这应该在第二页上重复单击下一步