如何将 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 的输入,类似于 我已经应用了你的修复。当我已经从数据库中获取足够数量的记录时,它工作得很好。当分页器的索引发生变化时,如何再次/或每次触发 db 函数?假设我已经加载了前 20 个元素,然后分页器工作正常,但总记录为 100,那么如何加载另外 80 个元素? 使用 MatPaginator 的服务器端分页是另一个问题 =) 我建议您先阅读 material.angular.io/components/table/overview#pagination 结合 material.angular.io/components/table/…。解决方案是使用 obervable 初始化 MatTableDataSource,每次更改分页时都会发出分页页面 这是使用高级数据源的好建议,它肯定会涉及到 observable。我得到了这个概念,而不是使用它。我创建了一个名为 on_page_change() 的函数,该函数绑定到分页的 page() 属性,它会调用新的 API。【参考方案2】:

这是@mateo-tibaquira 想法的一个更简单的版本。亮点包括:

DataSourceObservable 结合使用以捕获瞬时加载状态以及服务调用导致的任何错误。 根据后端服务调用返回的总数更新分页器length。 一个Page&lt;T&gt;泛型类,用于包装T类型的响应数组,添加分页头信息:pageSizepageIndextotalCount。 假设后端调用支持与&lt;mat-table&gt;&lt;mat-paginator&gt; 兼容的分页参数。

此代码基于优秀的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 不起作用

如何将选择标记选项值附加到Web服务角度4

如何将来自不同订阅的 ACR 附加到 AKS? [关闭]

Spark SQL:如何将新行附加到数据框表(来自另一个表)

如何使用来自localstorage的jquery将项目附加到DOM?

角度将组件附加到各个选项卡