Michal
Michal

Reputation: 9

create dynamic interface for material table datasource

I have a generic component for viewing query results containing dynamic fields.

I use mat-table to view the data, but the pagination and the sort features don't work.

The function setDataSource is called from parent component.

I think this is happening because the datasource declaration doesn't implement the interface.

How can I set datasource with dynamic interface?

My Html:

<mat-table matTableExporter matSort #exporter="matTableExporter" [dataSource]="dataSource" class="mat-elevation-z8">
    <ng-container *ngFor="let disCol of displayedColumns;let colIndex=index" matColumnDef="{{disCol}}">
        <mat-header-cell *matHeaderCellDef mat-sort-header>{{disCol}} </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element[disCol]}} </mat-cell>
    </ng-container>
    <mat-header-row mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[5, 10, 50]" showFirstLastButtons></mat-paginator>
<button mat-raised-button (click)="exporter.exportTable('xlsx', {fileName:'report', sheet: 'sheet 1', Props: {Author: 'Me'}})">Excel</button>

TypeScript:

displayedColumns: string[] = [];
dataSource: any = [];
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, {static: true}) sort: MatSort;

public setDataSource(data,column) {
    this.displayedColumns = column;
    this.dataSource = data;
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

Upvotes: 0

Views: 1849

Answers (2)

JuNe
JuNe

Reputation: 1997

I had a similar problem and solved it by generating a new datasource every time the data changes and then set the paginator and sorter.

EDIT: Add setter for paginator and sorter and change static attribute to false. Also add a check before setting the paginator and sorter in the setDataSource function.

@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; // change static to false here
@ViewChild(MatPaginator, {static: false}) set matPaginator(value: MatPaginator) {
  if(this.dataSource && value) {
    this.dataSource.paginator = value;
  }
}

@ViewChild(MatSort, {static: false}) sort: MatSort; // change static to false here
@ViewChild(MatSort, {static: false}) set matSort(value: MatSort) {
  if(this.dataSource && value) {
    this.dataSource.sort = value;
  }
}

public setDataSource(data,columns) {  // data -> array of elements; columns -> columns you wish to display
  this.displayedColumns = columns;        
  this.dataSource = new MatTableDataSource<any>(data);  // replace any with your data type
  if(this.paginator) {   // add check here
    this.dataSource.paginator = this.paginator;
  }
  if(this.sort) {  // add check here
    this.dataSource.sort = this.sort;
  }
}

Upvotes: 1

uminder
uminder

Reputation: 26150

In case the complete data is loaded into the client, you should use MatTableDataSource. This class is aimed to be used for filtering, sorting and pagination of a client-side data array.

When filtering, sorting and pagination are done server-side, the use of this class is not appropriate. In such cases, the relevant data may be kept in a simple array, hence no need to implement a specific interface. A good example is given at https://blog.angular-university.io/angular-material-data-table/.

Upvotes: 0

Related Questions