我正在尝试使用带有分页器的可扩展行的角度材质表,问题是,对于可扩展行使用自定义连接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);
}
组件的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的最新代码
我也尝试过删除评论推荐的人,这是使用AfterViewInit,也没用?
[编辑] 通过调试一个没有这个问题的案例(没有可扩展的行),差异在于这段代码,使用我自己的DataSource版本的可扩展行没有观察者,但是使用原生的,我错过了什么在我的数据源的定义?
答案 0 :(得分:0)
似乎角度材质中的表不是那么完整或灵活,所以我通过使用本机表标签和粗暴数据处理解决了这个问题。原生表被认为是一个很好的替代in this angular material github issue和also 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,但在本地它确实按预期工作