如果您不需要分页、排序或过滤,那么@leopal 的回答就可以了。如果您确实需要这些功能,请查看Angular Material博客条目:
Angular Material Data Table: A Complete Example (Server Pagination, Filtering, Sorting)。
它非常完整且解释得很好——而且太长了,甚至无法涵盖这里的亮点。我看到的一个差距是如何在应用过滤器后更新分页器的总长度......下面是我的工作代码。
页:
export class Page<T> extends Array<T> {
public static readonly DEFAULT_PAGE_SIZE: number = 10;
pageIndex: number;
pageSize: number;
totalCount: number;
constructor( pgIx?: number, pgSize?: number, tot?: number, items?: T[] )
{
super();
this.pageIndex = pgIx ? pgIx : 0;
this.pageSize = pgSize ? pgSize : 0;
this.totalCount = tot ? tot : 0;
if ( items && items.length > 0 ) {
this.push( ...items );
}
}
}
表状态:
import { Observable, BehaviorSubject, Observer } from "rxjs";
import { map, catchError, finalize,
debounceTime, distinctUntilChanged, startWith, tap, delay
} from "rxjs/operators";
import { CollectionViewer, DataSource } from "@angular/cdk/collections";
import { MatPaginator } from '@angular/material';
import { MyError } from '../model/error';
import { Page } from '../model/page';
export class MyTableState<T> implements DataSource<T>, Observer<Page<T>>
{
private items = new BehaviorSubject<Page<T>>( new Page<T>() );
private loading = new BehaviorSubject<boolean>(false);
private err = new BehaviorSubject<DruidError>( new DruidError(0, '') );
protected paginator: MatPaginator;
items$ = this.items.asObservable();
loading$ = this.loading.asObservable();
error$ = this.err.asObservable();
closed = false;
constructor( protected itemType: string ) {
}
haveError() : boolean {
const derr = this.err.getValue();
if ( derr && (derr.status !== 0 || derr.message) ) {
return true;
}
return false;
}
errorStatus() : number {
const derr = this.err.getValue();
if ( derr ) {
return derr.status;
}
return 0;
}
errorMessage() : string {
const derr = this.err.getValue();
if ( derr ) {
return derr.message;
}
return '';
}
noResults() : boolean {
const results = this.items.getValue();
return !results || results.length == 0;
}
isLoading() : Observable<boolean> {
return this.loading$;
}
totalCount() : number {
const cnt = this.items.getValue();
return ( cnt ? cnt.totalCount : 0 );
}
next( results: Page<T> ) : void {
console.debug( "Found items: ", this.itemType, results );
if ( this.paginator ) {
this.paginator.length = results.totalCount;
}
this.items.next( results );
}
error( errr: any ) : void {
console.error( "Error loading items: ", this.itemType, errr );
this.err.next( errr );
}
complete() : void {
console.debug( "Done loading items.", this.itemType );
this.loading.next( false );
}
addItem( item: T ) : void {
this.items.value.unshift( item );
}
connect( collectionViewer: CollectionViewer ) : Observable<Page<T>> {
this.closed = false;
return this.items$;
}
disconnect( collectionViewer: CollectionViewer ): void {
this.closed = true;
this.items.complete();
this.loading.complete();
this.err.complete();
}
protected preLoad() : void {
this.err.next( new DruidError(0,'') );
this.loading.next( true );
}
setPaginator( pgntr: MatPaginator ) : void {
this.paginator = pgntr;
}
/* In a derived class implement this and call it from your containing
* components in response to filter input, etc.
loadXyzs( offset: number = 0, limit: number = 10, predicates?: any ) : void
{
this.preLoad();
this.xyzService
.searchXyzs( offset, limit, predicates )
.subscribe( this );
}*/
};