如何将 MatPaginator 附加到来自角度材料表中服务器的数据源?
Posted
技术标签:
【中文标题】如何将 MatPaginator 附加到来自角度材料表中服务器的数据源?【英文标题】:How to attach MatPaginator to datasource coming from server in angular material table? 【发布时间】:2018-08-12 23:43:31 【问题描述】:我正在使用angular Material table 在我的 Angular 5 项目中创建网格。 我的数据来自 http 请求,并将其分配给 view.ts 文件中的一个名为 dataSourceNew 的变量。这里 dataSourceNew 具有动态内容和结构,因此我没有导出任何界面。
this.http.get('http://example.org?,headers: this.headers)
.subscribe(
res =>
this.displayedColumnsNew = res.record;
this.dataSourceNew = res.data;
this.matdatasource = new MatTableDataSource(this.dataSourceNew);
this.dataSourceNew.paginator = this.paginator;
console.log("got matdatasource object",this.matdatasource);
// attached the result of this log below
);
我能够在 html 文件中使用此语法成功创建数据表。
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSourceNew">
<ng-container *ngFor="let head of tableData.record; let i= index; " matColumnDef="head" (click)="setClickedRow(ddata) " [class.active]="ddata[primaryid] == selectedRow">
<mat-header-cell *matHeaderCellDef> tableData.gridhead[i]
</mat-header-cell>
<mat-cell *matCellDef="let element"> element[head] </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumnsNew"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumnsNew;">
</mat-row>
</mat-table>
</div>
现在我想在这个表上附加一个分页,为此我已经声明了这个
@ViewChild(MatPaginator) paginator: MatPaginator;
但是当我像这样将分页附加到 html 中的表格时,
<mat-paginator #paginator
[pageSize]="10"
[pageSizeOptions]="[5, 10, 20]"
[showFirstLastButtons]="true">
</mat-paginator>
我在控制台中收到以下错误,它破坏了我的应用程序。
我已经导入了这个
import MatPaginator, MatTableDataSource from '@angular/material';
在各自的 .ts 文件中。
Uncaught Error: Template parse errors:
Can't bind to 'pageSize' since it isn't a known property of 'mat-paginator'.
1. If 'mat-paginator' is an Angular component and it has 'pageSize' input, then verify that it is part of this module.
2. If 'mat-paginator' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.
当我记录 this.dataSourcenew 时: 此对象的分页器元素为空: 如何在不创建任何界面的情况下使用角度材质分页器?
更新:
在大卫的建议下: 我已将 MatPaginator 添加到主应用程序模块的导入中。现在分页块显示完美。
但当前记录显示为“0 of 0”。即使我有 14 条记录,并且分页功能(例如更改记录数、下一个、上一个等)也不起作用。我错过了什么?
更新 2:我已将属性 Length 应用于分页器标签。现在分页工作正常。问题是现在数据表没有改变当前的编号。的行。
更新 3:根据 Pierre Mallet 的建议,我已经完成了必要的更改。现在没有明确告诉 [length] 总记录是从 api 响应中推断出来的。分页器也与我的this.matdatasource = new MatTableDataSource([]);
正确绑定,所以到目前为止还没有进行明确的编码来实现这一点。
现在我只想先获取几条记录(比如说 20 条),然后想从后续请求中调用数据库,这样我就不需要一次访问数据库来获取所有记录。如何做到这一点?
【问题讨论】:
您还需要将 MatPaginator 添加到模块的导入中 @David 我已将 MatPaginator 添加到主应用程序模块的导入中。现在分页块显示完美。但当前记录显示为“0 of 0”。即使我有 14 条记录,并且分页功能(例如更改记录数、下一个、上一个等)也不起作用。 需要指定分页器的[length]属性。 material.angular.io/components/paginator/overview。这是一个完整的教程blog.angular-university.io/angular-material-data-table @David 谢谢。现在它显示总记录和下一个,上一个按钮工作正常但表格输出没有更新?有什么自定义函数要写吗? 你看过教程链接了吗? 【参考方案1】:在将分页器“链接”到 MatTableDataSource 之前,您必须等待它被实例化,所以通常,您会通过 @ViewChild(MatPaginator) paginator: MatPaginator;
监听 AfterViewInit 挂钩以获取分页器
但由于您的数据也是异步的,因此您应该
-
初始化一个空的数据源
数据准备就绪后填充数据源
在渲染视图后链接分页器
你能试试这个吗?
export class YourComponent implements AfterViewInit
private this.matdatasource;
// get refereence to paginator
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor (private http: HttpClient)
// 1/ init
this.matdatasource = new MatTableDataSource([]);
this.http.get('http://example.org',headers: this.headers)
.subscribe(res =>
// 2/ populate with data
this.matdatasource.data = res.data;
);
// 3/ link paginator when empty dataSource is created
// and paginator rendered
ngAfterViewInit()
this.dataSource.paginator = this.paginator;
【讨论】:
我现在正在尝试这个。你能告诉我如何传递当前索引、总记录等页面选项。等得到请求? 我认为总记录将从dataSource中数据数组的大小推断出来。您不必提供它。对于 currentIndex,它是 mat-paginator 组件(又名 pageIndex)material.angular.io/components/paginator/api#MatPaginator 的输入,类似于这是@mateo-tibaquira 想法的一个更简单的版本。亮点包括:
将DataSource
与Observable
结合使用以捕获瞬时加载状态以及服务调用导致的任何错误。
根据后端服务调用返回的总数更新分页器length
。
一个Page<T>
泛型类,用于包装T
类型的响应数组,添加分页头信息:pageSize
、pageIndex
和totalCount
。
假设后端调用支持与<mat-table>
和<mat-paginator>
兼容的分页参数。
此代码基于优秀的Angular Material 博客条目Angular Material Data Table: A Complete Example (Server Pagination, Filtering, Sorting),并大量借鉴。
custom-data-source.ts
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 Page from '../model/page';
export class CustomDataSource<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<any>( );
protected paginator: MatPaginator;
items$ = this.items.asObservable();
loading$ = this.loading.asObservable();
error$ = this.err.asObservable();
closed = false;
constructor( protected itemType: string )
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 );
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( );
this.loading.next( true );
setPaginator( pgntr: MatPaginator ) : void
this.paginator = pgntr;
model/page.ts
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 );
xyz-data-source.ts
import Xyz from '../model/xyz';
import CustomDataSource from './custom-data-source';
import XyzService from '../service/xyz-service';
export class XyzDataSource extends CustomDataSource<Xyz>
constructor( private xyzService: XyzService )
super( 'Xyz' );
loadXyz( offset: number = 0, limit: number = 10, predicates?: any ) : void
this.preLoad();
this.xyzService
.searchXyz( offset, limit, predicates )
.subscribe( this );
【讨论】:
【参考方案3】:您可以尝试@matheo/datasource
为您的数据库和数据源构建一个干净的设置,并让一切顺利到位。
我已经安装了具有各种分页响应的不同 API(也没有像 Firebase 这样的分页数据),并且我已经处理了所有这些案例的总数,没有任何问题。
更多详情请访问:https://medium.com/@matheo/reactive-datasource-for-angular-1d869b0155f6
如果您喜欢这个库,我可以帮助您解决用例 编码愉快!
【讨论】:
【参考方案4】:首先,实例化分页器
@ViewChild(MatPaginator) paginator: MatPaginator;
然后填充数据源
this.matdatasource = new MatTableDataSource([])
最后
this.dataSource.paginator = this.paginator;
检查this 以获得正确的理解
【讨论】:
以上是关于如何将 MatPaginator 附加到来自角度材料表中服务器的数据源?的主要内容,如果未能解决你的问题,请参考以下文章
没有 setTimeOut,MatSort 和 MatPaginator 不起作用
Spark SQL:如何将新行附加到数据框表(来自另一个表)