异步初始化MatPaginator

时间:2018-07-22 06:24:48

标签: angular asynchronous angular-material

我们在components中像

一样初始化MatPaginator。

@ViewChild(MatPaginator) paginator: MatPaginator;

并分配给在我们组件中定义为

MatTable DataSource

matTableDataSource.paginator = this.paginator;

当使用async管道和*ngIf组合异步初始化数据源时,这在用例中不起作用。

<div *ngIf="someDataObs | async as yourData else loading">
   <mat-table #table [dataSource]="yourData">
      ... your headers and columns
   </mat-table>
   <mat-paginator [pageSize]="10" showFirstLastButtons></mat-paginator>
</div>

注意:您可以使用mat-paginatordiv放在*ngIf下方,但这不是理想的解决方案,如果需要显示多个表,则更不适合在同一个组件中,只有一个后端异步调用。

由于mat-paginator将被异步初始化,因此使用下面的代码将不起作用,因为paginator将是null

ngAfterViewInit() {
  this.someDataObs = this.backendService.get()
    .map(value => {
      const matTableDataSource = new MatTableDataSource<SomeType>(value);
      matTableDataSource.paginator = this.paginator; // will be null here
      return matTableDataSource;
    });
}

要想实现这一目标,必须MatPaginator初始化后output property才能发出,但是目前尚不存在。

使用async管道和*ngIf使代码非常简洁,您不应避免使用它来克服此用例。

任何实现此目的的解决方案都是有帮助的。

4 个答案:

答案 0 :(得分:0)

很高兴,您的问题是* ngIf。

对于@ViewChild(MatPaginator) paginator: MatPaginator,当请求分页器时,在DOM中找不到它,并且它返回null。

此问题的一种解决方案是将您的* ngIf替换为带有display:none的语句。因此分页器将保留在DOM中。

答案 1 :(得分:0)

我只是遇到了同样的问题。这是一个已知问题,我认为他们可以更好地解决这个问题。

 @ViewChild(MatPaginator) set matPaginator( paginator: MatPaginator){
   this.dataSource.paginator = paginator;
 }
 @ViewChild(MatSort) set matSort( sort: MatSort){
   this.dataSource.sort = sort;
 }

https://github.com/angular/material2/issues/10205#issuecomment-465455599

答案 2 :(得分:0)

我测试了此Github issue解决方案,并且效果很好

只需将此* ngIf =“ pagination”添加到HTML的mat-paginator中即可:

<table mat-table [dataSource]="dataSource">

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>
  ......

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons 
*ngIf="pagination" > <!-- THIS!!! -->
</mat-paginator>

然后将此结构添加到您的组件中

export class TableComponent implements OnInit {
@Input('pagination') pagination: boolean;
@ViewChild(MatPaginator,  {static: false}) set matPaginator(paginator: 
MatPaginator) {
  if (this.pagination) {
    this.dataSource.paginator = paginator;
  }
}
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
....
}

答案 3 :(得分:0)

GitHub上还有另一种解决方案:

只需将此HIDDEN添加到表格之前 当HIDDEN == TRUE时,将不会在加载数据源之前呈现表:

<policies>
<inbound>
    <base />
    <choose>
        <when condition="@(context.Subscription.Id == "123")">
            <rate-limit-by-key calls="500" renewal-period="60" counter-key="@(context.Subscription.Id)" />
        </when>
        <when condition="@(context.Subscription.Name == "example-b")">
            <rate-limit-by-key calls="100" renewal-period="60" counter-key="@(context.Subscription.Id)" />
        </when>
        <otherwise>
            <rate-limit-by-key calls="10" renewal-period="60" counter-key="@(context.Subscription.Id)" />
        </otherwise>
    </choose>
</inbound>
<backend>
    <base />
</backend>...