【问题标题】: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>  

为什么不显示其他页面上的条目?

【问题讨论】:

    标签: typescript


    【解决方案1】:
    1. 您错过了lengthpageSize 选项,请将它们提供给mat-paginator,它应该会有所帮助:
    <mat-paginator [length]="personsFiltered.data.length" [pageSize]="5" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
    
    1. 您还需要在过滤功能中修复分页 - 详情如下。

    2a. 修复分页的第一种方法是从函数中删除这部分 (map(p =&gt; 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://stackoverflow.com/a/50269705/14556461

    在这种方法中,分页由 mat-paginator 自动完成,您的自定义代码会删除应该在下一页显示的数据 - 分页器无法加载更多数据,因为该函数会删除数据。

    2b. 另一种方法是更手动地进行分页 - 您可以使用来自mat-paginatorpage 事件,如下所示:

    <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();

    这就是它的工作原理,目前唯一的问题是性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      相关资源
      最近更新 更多