【问题标题】:angular material pagination not working with expandable row角度材料分页不适用于可扩展行
【发布时间】:2018-11-02 12:29:26
【问题描述】:

我正在尝试使用带有分页器的可扩展行的角度材料表,问题是,用于可扩展行的自定义连接 MatTableDataSource 分页停止工作,我在任何地方都找不到问题的答案。

所以,测试表数据是由这个存根服务给出的:

import { Injectable } from '@angular/core';
import { TableRow } from './table-row';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TestTableService {

  private testData : TableRow[] = [
    {id:1, name:'pi', value:3.14},
    {id:2, name:'euler', value:2.71},
    {id:3, name:'Feigenbaum constant', value:2.50290},
    {id:4, name:'Mills constant', value:1.30637},
    {id:5, name:'one', value:1},
    {id:6, name:'square root of 2', value:1.41421}
  ];

  constructor() { }

  public getData() : Observable<TableRow[]>
  {
    return of(this.testData);
  }
}

表格组件是:

import { Component, OnInit, ViewChild } from '@angular/core';
import { TestTableService } from './../test-table.service';
import { TableRow } from './../table-row';
import {MatPaginator, MatTableDataSource} from '@angular/material';
import { Observable, of} from 'rxjs';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-test-table',
  templateUrl: './test-table.component.html',
  styleUrls: ['./test-table.component.css'],
  animations: [
    trigger('detailExpand', [
      state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })),
      state('expanded', style({ height: '*', visibility: 'visible' }))
    ]),
  ],
})
export class TestTableComponent implements OnInit {
  tableData : myDataSource<TableRow> = new myDataSource();
  columnsToDisplay = ['id', 'name','value'];
  isExpansionDetailRow = (i: number, row: Object) => row.hasOwnProperty('detailRow');
  expandedElement = null;

  constructor(private testTable : TestTableService) { }

  @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    this.paginator = mp;
    this.tableData.paginator = this.paginator;
  }

  //@ViewChild(MatPaginator) paginator: MatPaginator;

  ngOnInit() {
    this.testTable.getData()
      .subscribe(table => this.tableData.data = table);
    //this.tableData.paginator = this.paginator;
  }

  expand(row){
    this.expandedElement = this.expandedElement == row ? null : row;
  }

  //setTimeout(() => this.tableData.paginator = this.paginator);

}

请注意我已经尝试了许多涉及分配分页器 的解决方案。

组件的html:

<table mat-table [dataSource]="tableData">
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef> Id </th>
    <td mat-cell *matCellDef="let row"> {{row.id}} </td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let row"> {{row.name}} </td>
  </ng-container>
  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef> Value </th>
    <td mat-cell *matCellDef="let row"> {{row.value}} </td>
  </ng-container>

  <ng-container matColumnDef="details">
    <td mat-cell *matCellDef="let detail"> 
      <!--
      <app-test-table-detail [show]="detail.element == expandedElement" ></app-test-table-detail>
        -->
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay"
    matRipple
    (click)="expand(row)"></tr>

  <tr mat-row *matRowDef="let row; columns: ['details']; when:isExpansionDetailRow"
    [@detailExpand]="row.element==expandedElement ? 'expanded' : 'collapsed'"
    style="overflow: hidden"></tr>
</table>

<mat-paginator [pageSizeOptions]="[3, 10, 20]" showFirstLastButtons></mat-paginator>

有趣的是,分页器给出了正确的数字但没有效果,我应该在流中处理它吗?在连接函数中?

[编辑] stackblitz 的最新代码

https://stackblitz.com/edit/angulartableexample?file=src%2Fapp%2Ftest-table%2Ftest-table.component.html

我也试过删评论的人推荐的,就是用AfterViewInit,也没用

[编辑] 通过调试一个没有这个问题的案例(没有可扩展的行),区别在于这段代码的 sn-p,使用我自己的 DataSource 版本的可扩展行没有观察者,但是使用本机有,我是我的数据源定义中缺少某些内容?

【问题讨论】:

    标签: angular html-table pagination angular-material angular6


    【解决方案1】:

    似乎angular material中的table不是那么完整或灵活,所以我通过使用native table tags和brute data processing解决了这个问题。原生表被认为是一个很好的替代品 in this angular material github issuealso here

    我知道它看起来很难看,但解决了这个问题,因为这个组件只应该以一种完整的方式(多列标题 + 排序 + 过滤 + 可扩展行)尽可能响应地处理表格,所以里面的额外代码组件不是问题。

    我还将分页器用作视图中的一个简单小部件,为控制器提供分页数据。

    最后,组件视图定义为:

    <table class="mat-table" style="overflow-y:scrol">
      <thead>
        <tr class="mat-header-row">
          <th rowspan="2" class="mat-header-cell" (click)="orderBy('id')">
            ID
          </th>
          <th colspan="2" rowspan="1" class="mat-header-cell">
            But can you do this?
          </th>
        </tr>
        <tr class="mat-header-row">
          <th class="mat-header-cell" (click)="orderBy('name')">
            Name
          </th>
          <th class="mat-header-cell" (click)="orderBy('value')">
            Value
          </th>
        </tr>
      </thead>
      <tbody>
        <tr class="mat-row" *ngFor="let element of showData" (click)="expand(element)">
          <td class="mat-cell"  *ngIf="element.detailRow == undefined">
            {{element.id}}
          </td>
          <td class="mat-cell" *ngIf="element.detailRow == undefined">
            {{element.name}}
          </td>
          <td class="mat-cell" *ngIf="element.detailRow == undefined">
            {{element.value}}
          </td>
          <td colspan="3" class="mat-cell" *ngIf="element.detailRow">
            <app-test-table-detail [show]="true" [id]="element.element.id"></app-test-table-detail>
          </td>
        </tr>
      </tbody>
    </table>
    
    <mat-paginator [pageSizeOptions]="[3, 10, 20]" showFirstLastButtons (page)="applyPaging()"></mat-paginator>
    

    和控制器,但过滤尚未实现

    import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
    import { TableRow } from './../table-row';
    import { PageEvent, MatPaginator } from "@angular/material";
    import { TestTableService } from './../test-table.service';
    
    @Component({
      selector: 'app-native-table',
      templateUrl: './native-table.component.html',
      styleUrls: ['./native-table.component.css']
    })
    export class NativeTableComponent implements AfterViewInit, OnInit {
    
      private order : string = "id";
      private reverse : boolean;
      private cacheData : TableRow[] = [];
      private filteredData : TableRow[] = [];
      private pageData : TableRow[] = [];
      private showData : any[] = [];
      private selectedElement : TableRow;
      private filters : any = null;
    
      constructor(private tableService : TestTableService) { }
    
      @ViewChild(MatPaginator) paginator: MatPaginator;
    
      ngOnInit(){
        this.tableService.getData()
          .subscribe(table => this.cacheData = table);
      }
    
      ngAfterViewInit() {
        this.clearFilters();
      }
    
      clearFilters() : void{
        this.filters = {
          id : undefined,
          name : ""
        }
        this.applyFilter();
      }
    
      applyFilter() : void{
        this.filteredData = this.cacheData.slice();
        //do filtering
        this.paginator.length = this.filteredData.length;
        this.applyOrder();
      }
    
      applyOrder() : void{
        this.filteredData.sort(this.orderRule(this.order,this.reverse))
        this.applyPaging();
      }
    
      applyPaging() : void{
        this.pageData = this.filteredData.slice(this.paginator.pageIndex*this.paginator.pageSize,(this.paginator.pageIndex+1)*this.paginator.pageSize);
        this.applySelected();
      }
    
      applySelected() : void{
        this.showData = [];
        this.pageData.forEach(element => element==this.selectedElement ? this.showData.push(element,{detailRow:true,element:element}) : this.showData.push(element))
      }
    
      orderBy(order : string) : void{
        if(this.order == order){
          this.reverse = !this.reverse
        }
        else{
          this.order = order;
          this.reverse = false;
        }
    
        this.applyOrder();
      }
    
      expand(element : TableRow) : void{
        this.selectedElement = this.selectedElement == element ? null : element;
        this.applySelected();
      }
    
      orderRule(onderIndex,reverse){
        return function(a,b){
          if(a[onderIndex] > b[onderIndex]){
            return reverse ? -1 : 1;
          }
          if(a[onderIndex] < b[onderIndex]){
            return reverse ? 1 : -1;
          }
          return 0;
        }
      }
    

    我已向the example stackblitz 添加了一个组件,不知道为什么@ViewChild 为分页器返回未定义,但在本地它确实按预期工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2019-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多