角度材质分页无法使用可扩展行

时间:2018-05-23 13:26:47

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

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

因此,测试表数据由此存根服务提供:

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

}

请注意我已经尝试了很多涉及分配分页器but still the result given is this的解决方案。

组件的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>
有趣的是,paginator给出了正确的数字但没有效果,我应该在流中处理它吗?在连接功能?

[编辑] stackblitz的最新代码

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

我也尝试过删除评论推荐的人,这是使用AfterViewInit,也没用?

[编辑] 通过调试一个没有这个问题的案例(没有可扩展的行),差异在于这段代码,使用我自己的DataSource版本的可扩展行没有观察者,但是使用原生的,我错过了什么在我的数据源的定义?

enter image description here

1 个答案:

答案 0 :(得分:0)

似乎角度材质中的表不是那么完整或灵活,所以我通过使用本机表标签和粗暴数据处理解决了这个问题。原生表被认为是一个很好的替代in this angular material github issuealso here

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

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

最后,组件视图定义为:

<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为paginator返回undefined,但在本地它确实按预期工作