Angular Material Table - Issues with async dataSource

15,741

You're assigning the new MatTableDataSource(this.invoices); to the this.dataSource.data but the data object is just the raw data. So just fix your code to

this.dataSource = new MatTableDataSource(this.invoices);

and you should be good.

Tipp: The MatTable datasource does not has to be a MatTableDataSource element. You can just pass the raw data to the [dataSource] attribute.

Share:
15,741
Admin
Author by

Admin

Updated on June 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to populate an Angular Material table with data loaded asynchronously from AWS DynamoDB, but the best I can do is render the table with the three expected items all returning properties in each cell as '[object Object]'.

    The process works like this:

    • At AllInvoicesComponent.ngOnInit(), do buildTable(),
    • Await DataService.getItems('invoices'),
    • Assign dataSource as new MatTableDataSource(AllInvoicesComponent.invoices)

    The 'async' pipe also does absolutely nothing for the dataSource attribute of the table.

    data.service.ts:

    import { Injectable } from '@angular/core';
    import * as aws from 'aws-sdk';
    import { Observable } from 'rxjs';
    import AuthService from '@app/services/auth.service';
    
    @Injectable({
      providedIn: 'root'
    })
    
    export class DataService {
    
      dynamodb;
      docClient;
    
      constructor(private auth: AuthService) {
        aws.config.credentials = new aws.Credentials(auth.credentials.accessKeyId, auth.credentials.secretAccessKey, null);
        aws.config.update({
            region: 'eu-west-1'
        })
    
        this.dynamodb = new aws.DynamoDB();
        this.docClient = new aws.DynamoDB.DocumentClient();
      }
    
      async getItems(tableName) {
        const params = {
            TableName: tableName
        }
    
        return new Promise((resolve, reject) => {
            this.dynamodb.scan(params, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data.Items);
                }
            })
        })
      }
    }
    

    all-invoices.component.ts:

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { Observable, from } from 'rxjs';
    import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
    
    import Invoice from '../invoice.interface';
    import { DataService } from '../../services/data/data.service';
    
    @Component({
      selector: 'app-all-invoices',
      templateUrl: './all-invoices.component.html',
      styleUrls: ['./all-invoices.component.scss']
    })
    
    export class AllInvoicesComponent implements OnInit {
    
      invoices;
    
      dataSource: MatTableDataSource<any>;
      @ViewChild(MatPaginator) paginator: MatPaginator;
      @ViewChild(MatSort) sort: MatSort;
    
      tableColumns = [
        'number',
        'reference'
      ]
    
      constructor(private database: DataService) {
    
      }
    
      ngOnInit() {
        this.buildTable();
      }
    
      async buildTable() {
        try {
            this.invoices = await this.database.getItems('invoices');
            this.dataSource = new MatTableDataSource(this.invoices);
        } catch(err) {
            console.error(`Error retrieving invoices: ${err.Message}`);
            // TODO:
        }
      }
    
    }
    

    all-invoices.component.html:

    <p>All Invoices</p>
    
    <br>
    
    <div class="spinner-container" *ngIf="dataSource.loading$ | async">
      <mat-spinner></mat-spinner>
    </div>
    
    <table mat-table [dataSource]="dataSource" matSort>
    
      <ng-container matColumnDef="number">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Number</th>
        <td mat-cell *matCellDef="let invoice">{{invoice.number}}</td>
      </ng-container>
    
      <ng-container matColumnDef="reference">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Reference</th>
        <td mat-cell *matCellDef="let invoice">{{invoice.reference}}</td>
      </ng-container>
    
      <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: tableColumns">
    
    </table>
    
    <mat-paginator [length]="dataSource.length" [pageSize]="25" [pageSizeOptions]="[5, 10, 25, 50]"></mat-paginator>