I managed with some support to feed data from a rest api call into a Materialdata table. Unfortunately the pagination nor sorting does work. My assumnption is that the initilization is somehow wrong. when loading the page I'm getting a ERROR TypeError: Cannot read property 'data' of undefined in the console. After 1-2 seconds I see the rest response and the data is shown in the table but wether sorting nor pagination is working. When clicking on table headers to sort the data there is no additional error.
accountlist-datasource.ts
import { Account } from './../_services/accounts';
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator, MatSort } from '@angular/material';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
export class AccountlistDataSource extends DataSource<Account> {
data: Account[];
constructor(private paginator: MatPaginator, private sort: MatSort) {
super();
}
connect(): Observable<Account[]> {
const dataMutations = [
observableOf(this.data),
this.paginator.page,
this.sort.sortChange
];
this.paginator.length = this.data.length;
return merge(...dataMutations).pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data]));
}));
}
disconnect() {}
private getPagedData(data: Account[]) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
}
private getSortedData(data: Account[]) {
if (!this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort.direction === 'asc';
switch (this.sort.active) {
case 'Name': return compare(a.Name, b.Name, isAsc);
case 'ID': return compare(+a.ID, +b.ID, isAsc);
default: return 0;
}
});
}
}
function compare(a, b, isAsc) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
accountlist.component.html
<h1>Institutions / Customer / Accounts</h1>
<div class="mat-elevation-z8">
<table mat-table class="full-width-table" [dataSource]="accounts.data.Documents" matSort aria-label="Elements">
<ng-container matColumnDef="Name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{row.Name}}</td>
</ng-container>
<ng-container matColumnDef="Account Number">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Institution ID</th>
<td mat-cell *matCellDef="let row">{{row['Account Number']}}</td>
</ng-container>
<ng-container matColumnDef="SHS_SAP_SOLD_TO">
<th mat-header-cell *matHeaderCellDef mat-sort-header>SAP Number</th>
<td mat-cell *matCellDef="let row">{{row.SHS_SAP_SOLD_TO}}</td>
</ng-container>
<ng-container matColumnDef="Country">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Country</th>
<td mat-cell *matCellDef="let row">{{row.Country}}</td>
</ng-container>
<ng-container matColumnDef="State/Province">
<th mat-header-cell *matHeaderCellDef mat-sort-header>State</th>
<td mat-cell *matCellDef="let row">{{row['State/Province']}}</td>
</ng-container>
<ng-container matColumnDef="City">
<th mat-header-cell *matHeaderCellDef mat-sort-header>City</th>
<td mat-cell *matCellDef="let row">{{row.City}}</td>
</ng-container>
<ng-container matColumnDef="Postal Code">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Postal Code</th>
<td mat-cell *matCellDef="let row">{{row['Postal Code']}}</td>
</ng-container>
<ng-container matColumnDef="Address 1">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let row">{{row['Address 1']}}</td>
</ng-container>
<ng-container matColumnDef="Created Date">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created Date</th>
<td mat-cell *matCellDef="let row">{{row['Created Date']}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #paginator
[length]="accounts.data.length"
[pageIndex]="0"
[pageSize]="50"
[pageSizeOptions]="[25, 50, 100, 250]">
</mat-paginator>
</div>
Accounts.ts
export interface Account {
Name: string;
ID: string;
City: string;
Country: string;
SHS_SAP_SOLD_TO: string;
'Account Number': string;
'Postal Code': string;
'Address 1': string;
'Address 2': string;
'State/Province': string;
}
accountslist.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { AccountlistDataSource } from './accountlist-datasource';
import { AzureService } from './../_services/azure.service';
@Component({
selector: 'app-accountlist',
templateUrl: './accountlist.component.html',
styleUrls: ['./accountlist.component.css']
})
export class AccountlistComponent implements OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
dataSource: AccountlistDataSource | null;
displayedColumns = [
'Name', 'Account Number', 'SHS_SAP_SOLD_TO', 'Country', 'State/Province', 'City', 'Postal Code', 'Address 1', 'Created Date'];
public accounts: any;
isLoading = true;
constructor(private azureService: AzureService) {
}
RenderDataTable() {
this.azureService.getAccountsAzure()
.subscribe(
res => {
this.accounts = new AccountlistDataSource(this.paginator, this.sort);
this.accounts.data = res as Account[];
console.log(this.accounts);
this.isLoading = false;
},
error => {
console.log('There was an error while retrieving data !!!' + error);
});
}
ngOnInit() {
this.RenderDataTable();
}
}