如何将 MatPaginator 与 MatTable 相关联,在模板中专门采用声明性数据源?

How do I associate a MatPaginator with a MatTable taking a declarative data source exclusively in the template?

我正在尝试将 MatPaginatorMatTable 相关联,后者的数据源输入 属性 只是在模板中声明,而不是从组件本身内部订阅。例如:

<table mat-table [dataSource]="allData$ | async" class="mat-elevation-z8">

通常,我会像这样将分页器与组件中的数据源相关联:

export class AppComponent {
  @ViewChild(MatPaginator) set paginator(paginator: MatPaginator) {
    if (paginator) {
      this.dataSource.paginator = paginator;
    }
  }
  dataSource;
  displayedColumns = ['first_name', 'last_name', 'email', 'ip_address'];

  constructor(private appService: AppService) {}

  ngOnInit() {
    this.appService.getData().subscribe((data) => {
      this.dataSource = new MatTableDataSource(data);
      this.dataSource.paginator = this.paginator;
    });
  }
}

不幸的是,这不适用于前一种方法,因为我们实际上并没有直接创建新的数据源,并且无法关联数据源并且通过 async 管道自动订阅声明。

这是显示问题的 StackBlitz:https://stackblitz.com/edit/angular-ivy-ebddd6?file=src/app/app.component.html

垫分页器可以“独立”使用,也可以在您有 MatTableDataSource 对象时使用。 属性 mat-table 的“数据源”可以是:数组、可观察对象或 MatTableDataSource。

要独立使用,您可以使用模板引用变量“pag”和变量“length”

<mat-paginator #pag [length]="length"
  [pageSizeOptions]="[5, 10, 20]"
  showFirstLastButtons>
</mat-paginator>

然后顺便用|slice

<table mat-table [dataSource]="allData$|async 
           |slice:pag.pageIndex*pag.pageSize:
                  (pag.pageIndex+1)*pag.pageSize" 
    class="mat-elevation-z8">

拼图的最后一块是使用管道抽头获取数组的长度

  allData$ = this.appService.getData().pipe(
    tap((res:any[])=>{
      this.length=res.length
    }))

为避免错误“AfterChecked”,您可以将 allData$ 赋值给包含在 setTimeOut

中的 ngOnInit 中的变量
   ngOnInit(){
    setTimeout(()=>{
      this.allData$ = this.appService.getData().pipe(
        tap((res:any[])=>{
          this.length=res.length
        }))
      })
    }

stackblitz

虽然没有在组件中订阅它,但我不明白为什么你不能做到 MatTableDataSource。我们只是在 map 和 return 中设置数据 MatTableDataSource,这样你就可以将分页器附加到它上面。对于 ViewChild matpaginator,我们需要设置 static: true 以便我们可以立即访问它,所以我会这样做:

@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

allData$ = this.appService.getData().pipe(
  map((data) => {
    let dataSource = new MatTableDataSource(data);
    dataSource.paginator = this.paginator;
    return dataSource;
  })
);

STACKBLITZ