【问题标题】:2 mat-paginator for the same data source2 mat-paginator 同一个数据源
【发布时间】:2019-06-19 19:28:27
【问题描述】:

我有一个垫表,每页最多可显示 100 个条目。起初,我在底部有一个垫子分页器,效果很好。现在我被要求在表格顶部设置一个分页器,在表格底部设置另一个分页器,因此如果用户正在寻找位于的条目,则无需一直向下滚动即可到达分页器顶端。
问题是两个分页器必须链接到同一个数据源。 我尝试为每个人提供不同的 id,使用 ViewChild 获取它们并将它们分配给相同的数据源,但它只适用于其中一个。

main.component.ts:

    flights: Flight[] =[];
    dataSource = new MatTableDataSource<Flight>(this.flights);
    @ViewChild('PAGINATOR') paginator: MatPaginator;
    @ViewChild('OTROPAGINATOR') paginatorOtro: MatPaginator;

main.component.html:

   <mat-paginator #PAGINATOR (page)="pageEvent = handlePage($event)" 
   [length]="length" [pageSizeOptions]="[25, 50, 100]" showFirstLastButtons> 
   </mat-paginator>

   <table mat-table ...> ... </table>

  <mat-paginator #OTROPAGINATOR (page)="pageEvent = handlePage($event)" 
  [length]="length" [pageSizeOptions]="[25, 50, 100]" showFirstLastButtons> 
  </mat-paginator>

将分页器链接到数据源:

    this.dataSource = new MatTableDataSource<Flight>(this.flights);
    this.dataSource.paginator = this.paginator;
    this.dataSource.paginator = this.paginatorOtro;

有人可以指导我吗?

【问题讨论】:

  • 我能想到的最好的方法是thisstackblitz。顶部分页器与底部分页器完美同步,不幸的是,底部分页器仅更改顶部分页器的设置,但不会更新表格。也许它对你有帮助。总体计划是有两个数据源,每个分页器一个,然后只同步分页器。
  • @FabianKüng 我没有考虑创建 2 个数据源。我想现在我只需要找出如何根据第二个分页器的更改正确更新第一个分页器和表格内容,这样我就可以模拟两者都适用于同一个表格。谢谢!
  • 如果您找到方法,请务必更新帖子,我很想知道您是如何做到的!
  • @FabianKüng 我找到了一种复制所需行为的方法,使用一些具有属性和方法的逻辑(来自 angular material paginator api)。只是有一点限制......我会发布一个答案并解释它。

标签: angular angular-material paginator mat-table


【解决方案1】:

我找不到为同一个数据源设置 2 个分页器的方法。我这样做的方式是使用数据源的副本设置第二个分页器,然后根据另一个分页器的更改移动每个分页器。

另外,我不能直接设置页面索引或每页项目的属性(表格没有刷新),所以所有的动作都是通过一些逻辑和分页器方法来实现的,比如 previousPage() 或 lastPage()。

唯一的限制是底部的分页器不能更改每页的项目,因为没有一种方法可以让我控制该属性。

您可以看到结果here。感谢FabianKüng 提供使用 2 个数据源并同步两个分页器的解决方案。

我希望这对某人有用。

【讨论】:

  • 伟大的工作人员,我只是在寻找这个,发现你的答案对我有用
【解决方案2】:

非常感谢Gustavo Alejandro 的解决方案。我将它用于我的 Angular v11 项目中。

一个简单的解决方案:

唯一的限制是底部的分页器不能改变 每页的项目,因为没有一种方法可以让我控制它 属性。

是否需要在 handlePageBottom() 方法内部使用新值为 topPaginator 发出事件:

handlePageTop(e): void {
    const {pageSize, pageIndex} = e;
    this.bottomPaginator.pageSize = pageSize;
    this.bottomPaginator.pageIndex = pageIndex;
  }

  handlePageBottom(e): void {
    const {pageSize, pageIndex} = e;
    this.topPaginator.pageSize = pageSize;
    this.topPaginator.pageIndex = pageIndex;
    this.topPaginator.page.emit(e);
  }

  ngAfterViewInit(): void {
    merge(
      this.topPaginator.page // we don't need both
    ).pipe(startWith({}),
      debounceTime(300)).subscribe() => {
       // do something
    });
  }
}

您不需要从@angular/material/paginator 导入PageEvent,因为您的模板将如下所示:

<mat-paginator #paginatorTop
               (page)="handlePageTop($event)" 
               [length]="resultsLength" 
               [pageSizeOptions]="[10, 25, 50, 100]" 
               [pageSize]="25">
</mat-paginator>

【讨论】:

  • 很好的解决方案。
【解决方案3】:

受@AlleXyS 答案的启发,我创建了完整的工作代码,以使用相同的数据源在材料表的顶部和底部完成垫分页器。虽然我不得不做出一些重大改变。重要的是将顶部分页器与 handlePaginatorBottom 方法连接起来,反之亦然。这样,两者就保持同步。当在handlePaginatorTop中使用底部分页器时,会发出一个页面事件以触发分页器一的页面observable加载相应的数据。

这是完整的实现,因为它有点棘手。

模板实现:

<mat-paginator
    #paginatorTop
    (page)="handlePaginatorBottom($event)"
    [length]="resultsLength"
    [pageSize]="30"
  ></mat-paginator>
  
  <div class="table-container">
    <table
      mat-table
      [dataSource]="data"
      multiTemplateDataRows
    >
// ...
    </table>
 </div>
 <mat-paginator
      #paginatorBottom
      (page)="handlePaginatorTop($event)"
      [length]="resultsLength"
      [pageSize]="30"
    ></mat-paginator>

类实现:

// ...

@ViewChild('paginatorTop', { static: false })
paginatorTop: MatPaginator
@ViewChild('paginatorBottom', { static: false })
paginatorBottom: MatPaginator

// ...

ngAfterViewInit() {
        
        this.paginatorTop.page
            .pipe(
                startWith({}),
                switchMap(() => {
                    // ...
                    // use switch map to load data via another observable
                })
                map((data) => {
                    this.isLoadingResults = false
                    this.resultsLength = data.count
                    return data.items
                }),
                catchError(() => {
                    this.isLoadingResults = false
                    return of([])
                })
            )
            .subscribe((data) => {
                this.data = data
            })
    }

    handlePaginatorTop(e): void {
        const { pageSize, pageIndex } = e
        this.paginatorTop.pageSize = pageSize
        this.paginatorTop.pageIndex = pageIndex
        this.paginatorTop.page.emit(e)
    }

    handlePaginatorBottom(e): void {
        const { pageSize, pageIndex } = e
        this.paginatorBottom.pageSize = pageSize
        this.paginatorBottom.pageIndex = pageIndex
    }

【讨论】:

    【解决方案4】:
    dataSource = new MatTableDataSource;
    @ViewChild('paginatorTop',{static:false}) topPaginator: MatPaginator;
    @ViewChild('paginatorBottom',{static:false}) bottomPaginator: MatPaginator;
         
    this.dataSource = new MatTableDataSource<any>(this.tableData);
    

    设置api数据到数据源

    【讨论】:

      猜你喜欢
      • 2020-03-09
      • 2020-07-15
      • 1970-01-01
      • 2018-06-01
      • 2019-07-08
      • 2021-06-07
      • 2019-10-23
      • 1970-01-01
      • 2019-06-19
      相关资源
      最近更新 更多